weak
引用在Swift中似乎不起作用,除非protocol
被声明为@objc
,这在纯Swift应用中是不希望的。
此代码给出编译错误(weak
不能应用于非类类型MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
我需要用@objc
作为协议的前缀,这样它就可以工作了。
问:完成weak
delegate
的“纯粹”快速方法是什么?
8条答案
按热度按时间b0zn9rqh1#
您需要将协议的类型声明为
AnyObject
。使用
AnyObject
时,您会说只有类可以遵循此协议,而结构体或枚举则不能。omvjsjqw2#
补充回答
委托是否应该是弱引用,我一直很困惑,最近我对委托有了更多的了解,什么时候使用弱引用,所以为了将来的读者,我在这里补充几点。
weak
关键字的目的是避免强引用循环(保留循环)。强引用循环发生在两个类示例对彼此有强引用时。它们的引用计数永远不会变为零,因此它们永远不会被释放。weak
,Swift结构体和枚举是值类型(当创建新示例时,它们的值会被复制),而不是引用类型,因此它们不会产生强 reference 循环。weak
引用始终是可选的(否则您将使用unowned
),并且始终使用var
(而不是let
),以便在释放可选引用时可以将其设置为nil
。weak
关键字,但是当子类需要一个对父类的引用时,它应该使用weak
关键字使其成为弱引用。weak
应该在你需要引用一个你不拥有的类时使用,而不仅仅是一个引用其父类的子类。当两个非层次的类需要相互引用时,选择一个弱类。你选择的那个弱类取决于具体情况。更多信息请参见this question的答案。*一般来说,委托应该标记为
weak
,因为大多数委托引用的类不是它们自己的。当子级使用委托与父级通信时,这是绝对正确的。文档建议对委托使用弱引用。(但也请参见this。)AnyObject
添加到协议的继承列表中。(过去使用class
关键字,而不是AnyObject
is preferred now。)进一步研究
阅读下面的文章帮助我更好地理解了这一点,他们还讨论了一些相关的问题,比如
unowned
关键字和闭包中的强引用循环。相关
2nbm6dog3#
AnyObject
是Swift中使用弱引用的官方方式。来自苹果:
若要防止强引用循环,应将委托声明为弱引用。有关弱引用的详细信息,请参阅类示例之间的强引用循环。将协议标记为仅限类以后将允许您声明委托必须使用弱引用。通过从AnyObject继承将协议标记为仅限类,如仅限类协议中所述。
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
eufgjt7s4#
**更新:**看起来手册已经更新了,我提到的例子已经被删除了。参见上面对@flainez答案的编辑。
**Original:**使用@objc是正确的方法,即使你没有与Obj-C互操作。它确保你的协议被应用到类而不是枚举或结构。参见手册中的“检查协议一致性”。
8tntrjer5#
弱限定符仅适用于引用对象。除非在协议上添加
@objc
、AnyObject
或class
限定符,否则符合协议的对象可能不是引用对象。因此,您需要这些限定符中的一个(并且推荐使用
AnyObject
,因为class
预计将被弃用)。顺便说一下,注意有时候需要在类和属性中添加
@objc
,即使是在“纯Swift”应用程序中也是如此。这与开发语言无关。它使编译器以与Objective-C运行时兼容的方式构建代码,这是一些操作系统接口所必需的(例如target/action和旧式键路径)3b6akqbq6#
baubqpgj7#
协议必须是AnyObject类的子类
示例如下
yizd12fk8#
苹果使用“NSObjectProtocol”而不是“类”。
这对我来说也很有效,并且消除了我在尝试实现自己的委托模式时看到的错误。