Swift Force-Unwrapping Exception Not Propagated

swift force-unwrapping exception not propagated

From the documentation:

Error Handling

Error handling is the process of responding to and recovering from
error conditions in your program. Swift provides first-class support
for throwing, catching, propagating, and manipulating recoverable
errors at runtime.

...

Representing and Throwing Errors

In Swift, errors are represented by values of types that conform to
the ErrorType protocol. This empty protocol indicates that a type can
be used for error handling.

(Note: ErrorType has been renamed to Error in Swift 3)

So with try/catch you handle Swift errors (values of types that conform to the ErrorType protocol) which are thrown.
This is completely unrelated to runtime errors and runtime exceptions
(and also unrelated to NSException from the Foundation library).

Note that the Swift documentation on error handling does not even use the
word "exception", with the only exception (!) in (emphasis mine) in:

NOTE

Error handling in Swift resembles exception handling in other
languages, with the use of the try, catch and throw keywords. Unlike
exception handling in many languages—including Objective-C—error
handling in Swift does not involve unwinding the call stack, a process
that can be computationally expensive. As such, the performance
characteristics of a throw statement are comparable to those of a
return statement.

The unwrapping of optionals which are nil does not throw a
Swift error (which could be propagated) and cannot be handled with
try.

You have to use the well-known techniques like
optional binding, optional chaining, checking against nil etc.

Not using force unwrapping in guard statement when throwing an ErrorType in Swift

The usual way to throw an error in a method which throws itself is to hand over the error to the caller by removing the do - catch block.

As a standard fetch is synchronous anyway you don't need performBlockAndWait() and you can safely forced downcast to [SeenPosts] because the fetch request is distinct.

If the fetch succeeds the array will be returned, in case of an error the error will be thrown.

func fetchMainQueuePost(predicate predicate: NSPredicate? = nil,
sortDescriptors: [NSSortDescriptor]? = nil) throws -> [SeenPosts] {

let fetchRequest = NSFetchRequest(entityName: "SeenPosts")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sortDescriptors
return try coreDataStack.mainQueueContext.executeFetchRequest(fetchRequest) as! [SeenPosts]
}

force unwrapping after checking if nil?

Yes, it is bad practice. Perhaps not in this case specifically but it is possible that some other thread could update the property and make it nil between this thread checking for nil and then force-unwrapping.

Just do:

if let arrayOfStrings = self.arrayOfStrings {
textLabel.text = arrayOfStrings[0]
}

There is no unnecessary variable here since you actually use the variable inside the if let.

Of course in this very specific case of trying to get the first value of an optional array, you can simply do:

textLabel.text = self.arrayOfStrings?.first

If you actually wanted something other than index 0, you should check the index:

if let arrayOfStrings = self.arrayOfStrings, someIndex < arrayOfStrings.count {
textLabel.text = arrayOfStrings[someIndex]
}

In none of these cases is the "extra" variable a waste of effort or memory. It is being used in a read-only capacity as a constant and Swift is smart enough not to create a complete copy of the array in the process.

Swift why unwrapping optional by guarding against NIL is not working

The type of s is still Optional, so whether you did a nil check or not is irrelevant. The nil check is done in runtime, while the type system is doing a compile-time check. The only way to ensure s can never be nil is via optional binding if let or guard let.

Concise Optional unwrapping

A few possibilities:

#1: The General. You can put multiple unwrapping variable declarations on one line.

if let item = displayText, value = Double(item) {
print("\(value)")
}

#2: The Hack. In your specific case, you can also default the empty optional to something you know isn't going to be a valid string representation of a Double:

if let value = Double(item ?? "") {
print("\(value)")
}

Swift: shortcut unwrapping of array of optionals

This solution will get you a new array with all values unwrapped and all nil's filtered away.

Swift 4.1:

let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.compactMap { $0 }

Swift 2.0:

let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.flatMap { $0 }

Swift 1.0:

let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.filter { $0 != nil }.map { $0! }


Related Topics



Leave a reply



Submit