Swift委托协议无法防止保留周期问题 [英] Swift delegate protocol cannot prevent retain cycle issue
问题描述
在Swift中,如果我创建了一个委托协议,则可以通过类和结构来遵循它.
In Swift, if I create a delegate protocol, it can be conformed to by class and struct.
protocol MyDelegate {
// Can be conformed to by class or struct
}
当我声明委托时出现问题.如果委托是一个类实例,我希望变量变弱以避免保留周期.如果是结构,则没有这种需要-实际上,Swift不允许我将委托变量设为弱.注意:我知道如何创建弱委托,但是关键问题是-如果创建可以弱的委托协议,除非仅使其成为符合类的协议,否则无法强制执行保留周期.
The issue comes up when I declare the delegate. If the delegate is a class instance, I want the variable to be weak to avoid retain cycle. If it is a struct, there is no such need - in fact, Swift won't allow me to make the delegate variable weak. Note: I know how to create a weak delegate, but the key question is - if you create a delegate protocol that can be weak, unless you make it class-conforming only, you cannot enforce retain cycle.
class MyClass {
// Want weak var here to avoid cyclical reference
// but Swift won't allow it because MyDelegate can be
// conformed by struct as well. Dropping weak means
// cyclical reference cannot be prevented
weak var delegate: MyDelegate?
}
class MyConformingClass: MyDelegate {
}
or
struct MyConformingStruct: MyDelegate {
}
由于非常规委托协议无法阻止保留周期,因此似乎始终需要声明该协议仅用于类.
It seems like we need to declare the protocol to be for class only at all times like this because a non regular delegate protocol cannot prevent retain cycles:
protocol MyDelegate: class {
}
Swift允许您以这种方式射击自己的脚这一事实似乎违背了其安全性设计理念.
The fact that Swift allows you to shoot yourself in the foot this way seems to go against its design philosophy in safety.
推荐答案
如果您确实想在类或结构上支持协议,则可以始终将委托存储在单独的基础变量中.这样,当委托是一个类时,您可能会遇到一个弱点.遵循以下原则:
If you really want to support a protocol on a class or struct you can always store the delegate in separate underlying variables. That way you can have one weak for when the delegate is a class. Along the lines of the following:
protocol MyDelegate {
// Can be conformed to by class or struct
}
class MyClass {
private weak var delegateFromClass: AnyObject?
private var delegateFromStruct: MyDelegate?
var delegate: MyDelegate? {
get {
return (delegateFromClass as? MyDelegate) ?? delegateFromStruct
}
set {
if newValue is AnyObject {
delegateFromClass = newValue as? AnyObject
delegateFromStruct = nil
} else {
delegateFromClass = nil
delegateFromStruct = newValue
}
}
}
}
class MyConformingClass: MyDelegate {
}
struct MyConformingStruct: MyDelegate {
}
print(" \(MyConformingClass() is AnyObject) \(MyConformingStruct() is AnyObject)")
这篇关于Swift委托协议无法防止保留周期问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!