I understand what optional are in Swift but I just encountered a ”Double Wrapped Optional’, where if I don’t use two '!' Xcode gives an complier error
Value of optional type 'String?' not unwrapped; did you mean to use '!' or ‘?'?
I have the following code, where app is of type NSRunningApplication.
let name: String = app.localizedName!
Why should I have to use two !? Isn’t one enough to unwrap the variable because it is of type var localizedName: String?.
Context:
Xcode want me to use let name: String = app.localizedName!!, otherwise it gives the compiler error above.
The app variable is defined as follow:
var apps = NSWorkspace().runningApplications.filter{$0.activationPolicy == NSApplicationActivationPolicy.Regular}
for app in apps{
//code posted above
…
}
So I know that app is not an optional and will always have a value, nor is it an optional application.
P.S. Is there a way to define type when using fast enumeration? Like for Foo(app) in apps where apps = [AnyObject].
You can unwrap optionals in 4 different ways: With force unwrapping, using ! With optional binding, using if let. With implicitly unwrapped optionals, using !
Even though Swift isn't sure the conversion will work, you can see the code is safe so you can force unwrap the result by writing ! after Int(str) , like this: let num = Int(str)! Swift will immediately unwrap the optional and make num a regular Int rather than an Int? .
However there is another data type in Swift called Optional, whose default value is a null value ( nil ). You can use optional when you want a variable or constant contain no value in it. An optional type may contain a value or absent a value (a null value). Non technically, you can think optional as a shoe box.
The problem is that NSWorkspace().runningApplications returns an
array of AnyObject which has to be cast to an array of
NSRunningApplication:
let apps = NSWorkspace().runningApplications as! [NSRunningApplication]
let filteredApps = apps.filter {
$0.activationPolicy == NSApplicationActivationPolicy.Regular
}
for app in apps {
let name: String = app.localizedName!
}
Here's why: app is of type AnyObject (id in Objective-C), and doing any lookup on AnyObject introduces a layer of optionality because of the possibility that the method doesn’t exist on the object. localizedName is itself Optional, so you end up with two levels of optional: the outer level is nil if the object doesn’t respond to localizedName, and the inner is nil if 'localizedName' is nil.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With