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
theErrorType
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 throw
n.
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 withtry
.
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
How to Draw a Single Point Line in iOS
Convert Request Function to Generic Type
Programmatically Go Back to Previous Viewcontroller in Swift
Formatting Phone Number in Swift
How to Draw a Transparent Stroke (Or Anyway Clear Part of an Image) on the Iphone
Alamofire Download in Background Session
Xcode Error on Simulator: Mgisdeviceoneoftype Is Not Supported on This Platform
Radial Gradient Background in Swift
Xcode 6 Standard Architectures Exclude Armv7S
Create and Perform Segue Without Storyboards
Run iPhone as an Ibeacon in the Background
iOS Uialertview Button to Go to Setting App
Could Not Launch Process Launch Failed: Timed Out Waiting for App to Launch
How to Use the Uisearchbar and Uisearchdisplaycontroller