weak
引用似乎在Swift中不起作用,除非protocol
被声明为@objc
,我不想在纯粹的Swift应用程序中使用。
此代码给出了编译错误(weak
不能应用于非类类型MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
我需要在协议前加上@objc
,然后才有效。
问题:什么是完成weak
delegate
的'纯'斯威夫特方式?
您需要将协议类型声明为class
。
protocol ProtocolNameDelegate: class {
// Protocol stuff goes here
}
class SomeClass {
weak var delegate: ProtocolNameDelegate?
}
我的理解是使用class
,你保证这个协议只能用于类,而不能用于其他东西,如枚举或结构。
我一直很困惑代表们是否应该是弱者。最近我学到了更多关于代表以及何时使用弱引用的知识,所以让我在这里为了未来的观众添加一些补充点。
weak
关键字的目的是避免使用strong reference cycles(保留周期)。当两个类实例具有相互强引用时,就会发生强引用循环。他们的引用计数永远不会变为零,因此它们永远不会被释放。weak
。 Swift结构和枚举是值类型(它们的值在创建新实例时被复制),而不是引用类型,因此它们不会产生强引用循环。weak
引用总是可选的(否则你会使用unowned
)并且总是使用var
(而不是let
),以便在解除分配时可选的设置为nil
。weak
关键字。但是,当一个孩子想要引用它的父级时,它应该通过使用weak
关键字使其成为弱引用。weak
,而不仅仅是引用其父级的子类。当两个非分层类需要相互引用时,选择一个为弱。你选择的那个取决于具体情况。有关详细信息,请参阅this question的答案。weak
,因为大多数代表都引用了他们不拥有的类。当孩子使用委托与父母沟通时,这肯定是正确的。对代表使用弱引用是documentation推荐的内容。 (但也见this。)AnyObject
添加到协议的继承列表中。 (过去你使用class
关键字,但AnyObject
is preferred now。)
protocol MyClassDelegate: AnyObject {
// ...
}
class SomeClass {
weak var delegate: MyClassDelegate?
}
阅读以下文章有助于我更好地理解这一点。他们还讨论了unowned
关键字等相关问题以及闭包发生的强引用周期。
AnyObject
是在Swift中使用弱引用的官方方式。
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate: AnyObject {
}
来自Apple:
为了防止强引用循环,应将委托声明为弱引用。有关弱引用的详细信息,请参阅类实例之间的强引用循环。将协议标记为仅限类将稍后允许您声明委托必须使用弱引用。您通过继承AnyObject将协议标记为仅仅类,如“仅类协议”中所述。
更新:看起来手册已更新,我所指的示例已被删除。请参阅上面@ @ flainez的回复编辑。
原文:即使你没有与Obj-C互操作,使用@objc也是正确的方法。它确保您的协议应用于类而不是枚举或结构。请参阅手册中的“检查协议一致性”。
示例如下
protocol NameOfProtocol: class {
// member of protocol
}
class ClassName: UIViewController {
weak var delegate: NameOfProtocol?
}
Apple使用“NSObjectProtocol”而不是“class”。
public protocol UIScrollViewDelegate : NSObjectProtocol {
...
}
这也适用于我并删除了我在尝试实现自己的委托模式时看到的错误。