Swift中,unowned只能应用于类和基于类的协议类型。weak可以正常工作。

9
请仔细阅读问题,因为它似乎是许多类似问题的重复,但实际上并不是。大多数其他问题使用带有“let”关键字的闭包来捕获对象初始化之前的弱引用或无主引用self。但我不这样做。
我的代码:
class Singleton : ObserverProtocol {

    static let shared = Singleton()

    private let obs : Observer = Observer.init()

    private init() { self.obs.responder = self }

    func observe(_ object : Any) {}

    fileprivate class Observer : NSObject {
        unowned var responder : ObserverProtocol!
        func observe(_ obj : Any) {
            self.responder.observe(obj)
        }
    }
}

fileprivate protocol ObserverProtocol : class {
    func observe(_ object : Any)
}

当我尝试编译时,unowned var responder : ObserverProtocol! 上会有一个错误提示:

'unowned' may only be applied to class and class-bound protocol types, not 'ObserverProtocol!'

如果我将 unowned 更改为 weak,则可以编译。 很明显,我不理解 unowned 的某些概念,所以我希望有人能给我解释一下。 P.S. 我知道有许多类似于这个问题的问题: UIView, CMDeviceMotionHandler : unowned may only be applied to class and class-bound protocol types 但我认为这不是我的情况。
1个回答

16

正如您所知,unowned 无法是可选项,但 weak 可能在某个时刻为 nil

据我所知,unowned 变量与隐式解包可选项不同。隐式解包适用于变量,该变量可能为 nil,但我们已经知道在访问的确切点上此变量不是 nil。然而,unowned 变量在任何时间点都不能为 nil

因此,您不能使用类型为 ObserverProtocol!unowned 常量。您需要摆脱 !

但如果您摆脱 !,则 Observer 需要一个初始化程序来初始化 responder


2
是的。我完全忘记了这段话“未拥有的引用应始终具有值。因此,ARC永远不会将未拥有的引用的值设置为nil,这意味着未拥有的引用使用非可选类型定义。” - iur
顺便说一句,在我个人看来,这是 Swift 核心团队没有考虑周全的一件事情之一。创建相互依赖的对象。他们半官方的回答是在这种情况下使用可选类型的强制解包,但似乎并不能涵盖所有可能的用例。这就迫使你要使用非“Swifty”的变通方法,或者降低了意图的清晰度。 - iur
@iur 我猜你随时都可以参与到Swift项目中,因为它是开源的。这听起来是一个有趣的话题去开始 :) - sCha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接