How to unwrap an optional option (ie 'var window?')

What I want to use:

if let window = UIApplication.shared.delegate?.window {

but the compiler won't let me, so I found a work-around:

if let _window = UIApplication.shared.delegate?.window, let window = _window {

Surely there is a better way!

You have an extra ? at the end of this line.

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

You don't have it in the second version though. So I'm a bit confused. Is that really the problem?

i think David is referring to the fact that this doesn't compile:

    if let window = UIApplication.shared.delegate?.window {
        window.becomeKey() // Error: Value of optional type 'UIWindow?' must be unwrapped to refer to member 'becomeKey' of wrapped base type 'UIWindow'
    }

    // and this is the workaround:

    if let _window = UIApplication.shared.delegate?.window, let window = _window {
        window.becomeKey()
    }

somehow window is returned as double optional but swift only unwraps one level of optionality in the first case.

1 Like
if let window = UIApplication.shared.delegate?.window ?? nil {…}

I am on the iPhone right now, so i didn’t try it out :thinking:

1 Like

The extra level of Optional indicates that the delegate may not implement the window property. @jmjauer's solution is my preferred one if you want to treat "doesn't implement the property" the same as "no window"…but only if you're writing general code that has to support delegates with or without the property. If you're writing code that's only intended to work with your UIApplicationDelegate, you should use ! here, because it's information you have that the compiler doesn't ("the particular UIApplicationDelegate here implements the window property").

3 Likes

probably this if i know that window must be there?

    let window = UIApplication.shared.delegate!.window!!
    window.becomeKey()

i take it this is only due to Obj-C interop and can't happen in practice in pure swift code?

found another oddity:

UIApplication.shared.delegate!.window = UIWindow() // Cannot assign to property: 'shared' is a get-only property

the error message looks quite strange given that the objects used here are references.

1 Like

So I tried your code - and it now compiles! But it will sure be hard to explain to someone in a code review :slight_smile:
Thanks for the help!!!

All this mess caused by the deprecation of 'keyWIndow'.

Even if I know my code has a property, I just won't use a "!" unless absolutely forced to. Personal style, YMMV.

This is SR-5475 (and we never found a satisfactory way to implement it), but the error message should definitely be clearer and it may be worth filing a separate bug about that.

1 Like

Well, you can always use this instead…

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

:grimacing:

I think it might better demonstrate what's going on, actually.

3 Likes

Here's my preferred pattern for unwrapping multiple levels of optionality:

if let window = UIApplication.shared.delegate?.window as? UIWindow {
    // ...
}
3 Likes

For me the following worked:

UIApplication.shared.delegate?.window??.rootViewController

You get UIViewController?.