为什么Swift 5可选链访问safeAreaInsets时window后需要两个问号?
Swift中
window??双重问号的底层逻辑 你遇到的双重问号本质是对两层嵌套的可选类型做连续的可选链式调用,和空合运算符??完全无关,只是语法上刚好连续写在一起。
类型链路拆解
UIApplication.shared.delegate的类型是UIApplicationDelegate?,末尾第一个?是对这个可选类型做可选解包,确保delegate不为空时才会继续访问后续成员。UIApplicationDelegate协议中的window属性自带两层可选属性:- 它是协议的可选成员(OC侧定义时标记了
@optional,桥接到Swift后访问这类成员必须额外加?或!解包) - 它本身的类型就是
UIWindow?(允许为空,比如未初始化主窗口的场景)
- 它是协议的可选成员(OC侧定义时标记了
- 所以
delegate?.window得到的类型是UIWindow??,也就是嵌套了两层的可选值:外层可选对应「协议是否实现了window成员」,内层可选对应「window实例是否存在」。 - 原有写法只加了一个
?,仅解包了第一层可选,剩下的UIWindow?类型还是可选值,无法直接访问safeAreaInsets成员,编译器要求你再加第二个?解包第二层可选,确认window实例不为空时才访问safeAreaInsets。
等价写法参考
window??.safeAreaInsets完全等价于连续解包两层可选的逻辑,你可以拆开来写更易读:
// 写法1:手动连续解包 var insets: UIEdgeInsets? if let delegate = UIApplication.shared.delegate, let window = delegate.window { insets = window.safeAreaInsets } // 写法2:显式标记两层可选 let optionalWindow: UIWindow?? = UIApplication.shared.delegate?.window let insets = optionalWindow??.safeAreaInsets
内容的提问来源于stack exchange,提问作者Random Nobody
相关产品推荐
相关产品推荐

