Swift可选可选 [英] Swift Optional of Optional

查看:88
本文介绍了Swift可选可选的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For a project of mine, I have to create a proxy AppDelegate that will forward calls to a another AppDelegate.

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

UIApplicationDelegate havs a var window: UIWindow?. My question is, why can't I do this:

private lazy var realAppDelegate: UIApplicationDelegate = {
    return AppDelegate()
}()

var window: UIWindow? {
    get {
        return realAppDelegate.window
    }
    set {
        realAppDelegate.window = newValue
    }
}

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

有人知道为什么吗?

推荐答案

UIApplicationDelegate 协议的属性窗口声明如下:

The property window of UIApplicationDelegate protocol is declared like this:

optional var window: UIWindow? { get set }

这意味着它是可选属性(在感觉实现 UIApplicationDelegate 协议的类不被要求实现/拥有此属性,就像你有 Objective-C中的@optional ,该属性属于可选类型 可选< UIWindow> (或 UIWindow?)。

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<UIWindow> (or UIWindow?).

这就是为什么你最后有双重可选类型,因为 window 属性可能会或可能不会在realDelegate中实现,如果是,则它本身的类型为可选< UIWindow> / 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>/UIWindow?.

所以基本上你想要的是返回 window realAppDelegate 的属性...仅当 realAppDelegate 决定时声明该属性本身(它不需要这样做,因为它是选项al var )。

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).


  • 如果 realAppDelegate 做了没有实现 window 本身,你可能打算返回 nil UIWindow?

  • 如果您的 realAppDelegate 确实实现了窗口属性,然后你需要按原样返回它(这个实现返回一个实际的 UIWindow 或一个 nil 一个)。

  • 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).

最简单的方法是使用nil-coalescing运算符 ?? a ?? b 意思是如果a是非零,则返回a,但如果a为nil,则返回b(如果 a 是键入 T?,然后整个表达式返回一个 T 类型的对象,在你的情况下 T 是类型 UIWindow?)。

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实现setter,这是另一个问题。根据这个SO答案,直接访问设置者协议的可选属性似乎不可能。但你可以设想一个黑客来解决这个问题,通过声明另一个协议使这个窗口属性要求成为强制性,然后尝试在setter中强制转换它:


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可选可选的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆