Swift可选可选

对于我的项目,我必须创建一个代理AppDelegate,它将调用转发到另一个AppDelegate。

UIApplicationDelegate有一个var window: UIWindow? 。 我的问题是,为什么我不能这样做:

 private lazy var realAppDelegate: UIApplicationDelegate = { return AppDelegate() }() var window: UIWindow? { get { return realAppDelegate.window } set { realAppDelegate.window = newValue } } 

该代码的问题是realAppDelegate.window是一个UIWindow??

有人知道为什么吗?

UIApplicationDelegate协议的属性window声明如下:

 optional var window: UIWindow? { get set } 

这意味着它是一个可选属性 (在某种意义上说“实现UIApplicationDelegate协议的类不被要求实现/具有此属性 ”,就像在Objective-C中有@optional那样),并且该属性是可选类型 Optional (或UIWindow? )。

这就是为什么你最后有双重可选类型的原因,因为那个window属性可能会或者可能不会在realDelegate中实现,如果是,它本身就是Optional / UIWindow?


所以基本上你想要的是返回你的realAppDelegatewindow属性…只有当realAppDelegate决定声明该属性本身时(它不需要这样做,因为它是optional var )。

  • 如果realAppDelegate没有实现window本身,你可能打算返回一个nil UIWindow? 结果是。
  • 如果你的realAppDelegate确实实现了window属性,那么你需要按原样返回它(这个实现返回一个实际的UIWindow或者一个nil )。

最简单的方法是使用nil-coalescing运算符?? 在斯威夫特。 a ?? b a ?? b表示“如果a是非nil,则返回a,但如果a为nil,则返回b”(如果aT?类型,则整个表达式应返回T类型的对象,其中in你的情况TUIWindow?类型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 } ... } 

要实现setter,这是另一个问题。 根据这个SO答案 ,直接访问协议的可选属性的setter似乎是不可能的。 但你可以想象一个黑客来解决这个问题,通过声明另一个使这个window属性要求成为必需的协议,然后尝试在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 } } } ... } 

财产的声明是

 optional var window: UIWindow? { get set } 

开头的optional意味着该属性根本不必存在,那是第二个?

UIApplicationDelegate是一个协议,实现它的类不必实现所有内容。