Swift可选可选 [英] Swift Optional of Optional
问题描述
对于我的项目,我必须创建一个代理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?$ c结果是$ c>。
- 如果您的
realAppDelegate
确实实现了窗口
属性,然后你需要按原样返回它(这个实现返回一个实际的UIWindow
或一个nil
一个)。
- If the
realAppDelegate
did not implementwindow
itself, you probably intend to return anil
UIWindow?
as a result. - If your
realAppDelegate
did actually implement thewindow
property, then you need to return it as is (wether this implementation returns an actualUIWindow
or anil
one).
最简单的方法是使用nil-coalescing运算符 ?? $在Swift中c $ c>。
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屋!