1

I have the following extension

extension UIWindow {
    static var key: UIWindow! {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

I can use it without optional chaining in the following case

Case 1

UIWindow.key.addGestureRecognizer(UIGestureRecognizer())

Case 2

let key: UIWindow = UIWindow.key
key.addGestureRecognizer(UIGestureRecognizer())

But, when use it in the following case, I will get a compiler error

Case 3 (Not working)

let key = UIWindow.key
// value of optional type 'UIWindow?' must be unwrapped to refer to member 'addGestureRecognizer' of wrapped base type 'UIWindow'
key.addGestureRecognizer(UIGestureRecognizer())

May I know why it is so? Why the compiler cannot recognise key as UIWindow, without having programmer to declare its type explicitly?

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

1 Answers1

2

This behaviour is introduced in SE-054: Abolish ImplicitlyUnwrappedOptional type. The point is to limit the use of implicitly unwrapped optionals.

As the proposal describes:

If the expression can be explicitly type checked with a strong optional type, it will be.

So the "explicitly" unwrapped optional is always preferred, when no other information is provided. The key in let key = UIWindow.key is of type UIWindow?.

It's only when you, e.g. provide an explicit type annotation : UIWindow, that the right hand side being of type UIWindow? won't typecheck anymore, and so the compiler has to implicitly unwrap the UIWindow!.

The rationale is:

This model is more predictable because it prevents IUOs from propagating implicitly through the codebase, and converts them to strong optionals, the safer option, by default.

Sweeper
  • 213,210
  • 22
  • 193
  • 313