3

I know what the ?? is when used as an operator but what does it mean when it is on a Type?

I have a struct in my project called MyStruct and the autocompletion of a particular var tells me it is of type MyStruct??

Not really sure what that means or how to unwrap it safely.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • 6
    It is `Optional>`, a "optional optional MyStruct". – Martin R Jul 25 '16 at 12:17
  • 3
    Nested optionals: `Optional(Optional(value))`. Unwrap twice. – Eric Aya Jul 25 '16 at 12:17
  • Typical example `UIApplicationDelegate.window`, an optional property that can contain an optional. Or indexing an optional dictionary. – Sulthan Jul 25 '16 at 12:17
  • Safely unwrap: `var myStruct: MyStruct?? = MyStruct()` `if let middleOpt = myStruct, myStruct = middleOpt{}` – Yury Jul 25 '16 at 12:23
  • 2
    Examples: http://stackoverflow.com/questions/27225232/two-or-more-optionals-in-swift, http://stackoverflow.com/questions/28901893/why-is-main-window-of-type-double-optional. – Martin R Jul 25 '16 at 12:25

1 Answers1

4

As others have said, it's a double Optional, completely unrelated to the nil coalescence operator (??).

To unwrap it, you just unwrap a regular optional, twice:

let doubleOptional: MyStruct?? = MyStruct()

guard let singleOptional = doubleOptional else {
    //first unwrapping failed
}

guard let wrappedValue = singleOptional else {
    //second unwrapping failed
}

//use wrappedValue

These are quite uncommon, but there are times when they're useful.

For example, consider you have a data structure that stores an average of an array. The array might be empty, thus the average should be allowed to be nil, to indicate there is no average. Suppose calculating this average is very expensive and we want to store it in a caching layer. This caching layer could have a double optional representing that average. If the value is Optional.None (i.e. nil), we know the cache doesn't have a value yet, thus it needs to be computed. If the value is Optional.Some(Optional.None), we know the cache has a value, but that there is no valid average (i.e. the array was empty. Lastly, the value could be Optional.Some(Optional.Some(/*...*/)), which represents a valid cache value of a valid average.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • 1
    Thanks. Makes sense when you think about it. I have a task which may return an error or may return a result. That result may have some value or may be nil. So the result is ??. Sorted now anyway. Thanks – Fogmeister Jul 25 '16 at 12:51
  • It's part of a networking framework. The errors are server errors returned to a completion block. Would do otherwise. – Fogmeister Jul 25 '16 at 14:17