Why Is Main Window of Type Double Optional

Why is main window of type double optional?

@matt has the details, but there is a (somewhat horrible, somewhat awesome) workaround. (See edit below, though)

let window = app.delegate?.window??.`self`()

I will leave the understanding of this line of code as an exercise for the reader.

OK, I lie, let's break it down.

app.delegate?.window

OK, so far so good. At this point we have the UIWindow?? that is giving us a headache (and I believe is a bug in Swift disconnect between Swift and Cocoa). We want to collapse it twice. We can do that with optional chaining (?.), but that unwraps and rewraps, so we're back where we started from. You can double-optional-chain, though, with ??. which is bizarre, but works.

That's great, but ?? isn't a legal suffix operator. You have to actually chain to something. Well, we want to chain back to itself (i.e. "identity"). The NSObject protocol gives us an identity method: self.

self is a method on NSObject, but it's also a reserved word in Swift, so the syntax for it is `self`()

And so we get our madness above. Do with it as you will.

Note that since ??. works, you don't technically need this. You can just accept that view is UIWindow?? and use ??. on it like view??.frame. It's a little noisy, but probably doesn't create any real problems for the few places it should be needed.

(*) I used to think of this as a bug in Swift, but it's not fixable directly by optional chaining. The problem is that there is no optional chaining past window. So I'm not sure where the right place to fix it is. Swift could allow a postfix-? to mean "flatten" without requiring chaining, but that feels odd. I guess the right operator would be interrobang delegate?.window‽ :D I'm sure that wouldn't cause any confusion.

EDIT:

Joseph Lord pointed out the better solution (which is very similar to techniques I've been using to avoid trivial if-let, but hadn't thought of this way before):

let window = app.delegate?.window ?? nil // UIWindow?

I agree with him that this is the right answer.

Swift Optional of Optional

The property window of UIApplicationDelegate protocol is declared like this:

optional var window: UIWindow? { get set }

That means that it is an optional property (in the sense that "the class implementing the UIApplicationDelegate protocol is not requested to implement/have this property", like when you have @optional in Objective-C), and that property is of optional type Optional (or UIWindow?).

That's why you have the double-optional type in the end, because that window property may or may not be implemented in realDelegate, and if it is, it will be itself of type Optional/UIWindow?.


So basically what you want is to return the window property of your realAppDelegate… only if that realAppDelegate decided to declare that property itself (which it isn't requires to do, as it's optional var).

  • If the realAppDelegate did not implement window itself, you probably intend to return a nil UIWindow? as a result.
  • If your realAppDelegate did actually implement the window property, then you need to return it as is (wether this implementation returns an actual UIWindow or a nil one).

The easiest way to do that is to use the nil-coalescing operator ?? in Swift. a ?? b meaning that "if a is non-nil, then return a, but if a is nil, return b" (where if a is of type T?, then the whole expression is expected to return an object of type T, where in your case T is the type UIWindow?).

var window: UIWindow? {
get {
// If realAppDelegate.window (of type UIWindow??) is not implemented
// then return nil. Otherwise, return its value (of type UIWindow?)
return realAppDelegate.window ?? nil
// That code is equivalent (but more concise) to this kind of code:
// if let w = realAppDelegate.window { return w } else return nil
}
...
}

To implement the setter, that's another problem. According to this SO answer, directly accessing to the setter of an optional property of a protocol doesn't seem to be possible. But you can imagine a hack to workaround this, by declaring another protocol that makes this window property requirement mandatory, then try to cast to it in the setter:

@objc protocol UIApplicationDelegateWithWindow : UIApplicationDelegate {
var window: UIWindow? { get set }
}

class AppDelegateWrapper : UIApplicationDelegate {
...
var window: UIWindow? {
get {
return realAppDelegate.window ?? nil
}
set {
if let realAppDelWithWindow = realAppDelegate as? UIApplicationDelegateWithWindow
{
// Cast succeeded, so the 'window' property exists and is now accessible
realAppDelWithWindow.window = newValue
}
}
}
...
}

Swift: why do I need optionals anyways?

Optionals

If you know for sure that a variable should never be nil, you can force unwrap an optional using ! or declare as implicitly unwrapped using String!. This will cause a crash when it is nil, exactly like you want.

But, with some variables it is reasonable for them to be nil. For example, a User model whose age variable isn't set because the user didn't supply it.

Explicitly marking them as optional and unwrapping them using if let forces you to think about nullability. In the end, this creates more robust code.

I don't think it leads to shorted code. Where in Objective-C you would use if var != nil you use if let var = var in Swift. Sending a message to nil in Obj-C is a noop, you can get the same behavior in Swift using var?.method(). It's kinda the same in the end.

Casting (as)

A big reason you need casts right now in Swift is because some Objective-C methods return id, which was no problem in Obj-C but causes trouble in Swift. I expect this to diminish as Swift becomes more popular and frameworks are adapted.

Updated code

I quickly looked over your code and it looks you don't need half those casts. This is from the top of my head:

if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("Home") as? UIViewController {
if let window = UIApplication.sharedApplication().delegate?.window {
window.rootViewController = viewController

UIView.transitionWithView(window, duration: 0.2, options: .TransitionCrossDissolve, animations: {
window.rootViewController = viewController
}, completion: nil);
}
}

Swift ?? on a type

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.

Why are two exclamation points needed in optional type not unwrapped?

You need two ! because the type is a nested optional (UIWindow??).

Like this:

let nested: Int?? = 3

// the safe way
if let innerValue = nested {
// innerValue is of type Int?
if let unwrapped = innerValue {
// unwrapped is of type Int
}
}

What does ?? mean on a variable declaration in Swift case let pattern matching?

In the context of pattern matching, x? is the “optional pattern” and equivalent to .some(x). Consequently, case x?? is a “double optional pattern” and equivalent to .some(.some(x)).

It is used here because UIApplication.shared.delegate?.window evaluates to a “double optional” UIWindow??, compare Why is main window of type double optional?.

Therefore

if case let presentationAnchor?? = UIApplication.shared.delegate?.window

matches the case that UIApplication.shared.delegate is not nil and the delegate implements the (optional) window property. In that case presentationAnchor is bound to the “doubly unwrapped” UIWindow.

See also Optional Pattern in the Swift reference:

An optional pattern matches values wrapped in a some(Wrapped) case of an Optional enumeration. Optional patterns consist of an identifier pattern followed immediately by a question mark and appear in the same places as enumeration case patterns.

Two (or more) optionals in Swift

(Updated for Swift >=3)

"Double optionals" can be useful, and the Swift blog entry "Optionals Case Study: valuesForKeys" describes an application.

Here is a simplified example:

let dict : [String : String?] = ["a" : "foo" , "b" : nil]

is a dictionary with optional strings as values. Therefore

let val = dict[key]

has the type String?? aka Optional>. It is .none (or nil)
if the key is not present in the dictionary, and .some(x) otherwise. In the second
case, x is a String? aka Optional and can be .none (or nil)
or .some(s) where s is a String.

You can use nested optional binding to check for the various cases:

for key in ["a", "b", "c"] {

let val = dict[key]
if let x = val {
if let s = x {
print("\(key): \(s)")
} else {
print("\(key): nil")
}
} else {
print("\(key): not present")
}

}

Output:

a: foo
b: nil
c: not present

It might be instructive to see how the same can be achieved with pattern matching
in a switch-statement:

let val = dict[key]
switch val {
case .some(.some(let s)):
print("\(key): \(s)")
case .some(.none):
print("\(key): nil")
case .none:
print("\(key): not present")
}

or, using the x? pattern as a synonym for .some(x):

let val = dict[key]
switch val {
case let (s??):
print("\(key): \(s)")
case let (s?):
print("\(key): nil")
case nil:
print("\(key): not present")
}

(I do not know a sensible application for more deeply nested optionals.)

What does the double question mark means at the end of the type?

Double?? is shorthand notation for Optional>, which is simply a nested Optional. Optional is a generic enum, whose Wrapped value can actually be another Optional and hence you can create nested Optionals.

let optional = Optional.some(2)
let nestedOptional = Optional.some(optional)

The type of nestedOptional here is Int??.

For your specific example, item.first is Double??, since item itself is of type [Double?] and Array.first also returns an Optional, hence you get a nested Optional.

Your compactMap call on data achieves nothing, since you call it on the outer-array, whose elements are non-optional arrays themselves. To filter out the nil elements from the nested arrays, you need to map over data and then call compactMap inside the map.

let nonNilData = data.map { $0.compactMap { $0 } } // [[100, 35.6], [110, 42.56], [120, 48.4], [200]]


Related Topics



Leave a reply



Submit