How do you unwrap a string that is returned as:
(Optional(Optional "blue"))
var cityName = String() if let cityAnno = annotation as MGLAnnotation! { cityName = String(stringInterpolationSegment: cityAnno.title!) } cityLabelName.text = ("\(cityName), \(county)")
cityLabelName prints out as (Optional "New York")
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? .
Given a double optional such as this doubly wrapped String
:
let a: String?? = "hello" print(a as Any) // "Optional(Optional("hello"))\n"
@Leo, showed that you could use optional binding twice:
if let temp = a, let value = temp { print(value) // "hello\n" }
or force unwrap twice:
print(value!!) // don't do this - you're just asking for a crash
Here are 5 more methods you can use to safely unwrap a double optional:
Method 1:
You can also use pattern matching:
if case let value?? = a { print(value) // "hello\n" }
As @netigger noted in their answer, this can also be written as:
if case .some(.some(let value)) = a { print(value) // "hello\n" }
which while less concise might be a bit easier to read.
Method 2:
Alternatively, you can use the nil coalescing operator ??
twice:
print((a ?? "") ?? "") // "hello\n"
Note: Unlike the other methods presented here, this will always produce a value. ""
(empty String
) is used if either of the optionals is nil
.
Method 3:
Or you can use the nil coalescing operator ??
with optional binding:
if let value = a ?? nil { print(value) // "hello\n" }
How does this work?
With a doubly wrapped optional, the value held by the variable could be one of 3 things: Optional(Optional("some string"))
, Optional(nil)
if the inner optional is nil
, or nil
if the outer optional is nil
. So a ?? nil
unwraps the outer optional. If the outer optional is nil
, then ??
replaces it with the default value of nil
. If a
is Optional(nil)
, then ??
will unwrap the outer optional leaving nil
. At this point you will have a String?
that is nil
if either the inner or outer optional is nil
. If there is a String
inside, you get Optional("some string")
.
Finally, the optional binding (if let
) unwraps Optional("some string")
to get "some string"
or the optional binding fails if either of the optionals is nil
and skips the block.
Method 4:
Also, you can use flatMap
with optional binding:
if let value = a.flatMap({ $0 }) { print(value) // "hello\n" }
Method 5:
Conditionally cast the value to the type. Surprisingly, this will remove all levels of optionals:
let a: String?? = "hello" let b: String??????? = "bye" if let value = a as? String { print(value) // "hello\n" } print(b as Any) // "Optional(Optional(Optional(Optional(Optional(Optional(Optional("bye")))))))\n" if let value = b as? String { print(value) // "bye\n" }
Try
var a:String?? = "1" print((a)) if let b = a,c = b{ print(c) }
Screenshot of playground
Also you can force unwrap,but it it is not secure
let d = a!!
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