让我们假设我们有一个协议
protocol MyProtocol {
fun someFunc()
}
class AClass {
var delegate: MyProtocol?
}
AClass不关心委托是类还是结构。我想要的是,有时委托可以是一个类,有时它可以分配给一个结构。
我的问题是,我是否应该让代表变得"软弱"。
如果是这样的话,我必须使MyProtocol成为一个"类协议",这样委托就只能是一个类。如果没有,当我将委托分配给类时,我如何避免保留循环?
谢谢你的提示!
应该使委托成为"弱">
答案是,如果MyProtocol
不限于类,则不能使其变弱,编译器不会允许。
之所以出现上述情况,是因为struct
s是值类型。没有一个引用可以是强引用也可以是弱引用,因为在分配委托时,逻辑上会复制整个结构。
如何避免保留周期?
这意味着您必须小心您的委托不包含对类实例的强引用。因此,例如
struct ConcreteDelegate: MyProtocol
{
fun someFunc() {}
var instance: AClass
init()
{
instance = AClass()
instance.delegate = self
}
}
导致参考循环。可以通过将instance
声明为来破坏它
weak var instance: AClass!
或者,更好的解决方案(IMO)是,协议函数可以将实例作为参数传递,这样委托就不需要存储对实例的引用。
protocol MyProtocol {
func someFunc(caller: AClass)
}
您将在许多地方看到Cocoa中采用的上述方法,例如表视图数据源协议。
我想您忘记了struct
不是引用类型,而是值类型。这意味着类在内存堆中有一个引用,但有结构,枚举没有。记住这个事实,如果您的协议的委托是struct
,那么放置weak
就没有意义,因为它不会导致保留循环
当您只使用类时,您需要担心保留周期。如果你的协议委托是一个类,那么放weak
如果你认为你的类有你的协议的引用,那么你的协议可以有你的类的引用,放weak
,这就是保留周期。
如果您想检查它,请在测试时放入deinit
函数,看看您的类是否正确卸载并且没有保存在内存中。这基本上就是我所知道的,希望它能帮助你。