nwa*_*les 42 delegates memory-leaks memory-management swift strong-reference-cycle
有人可以解释何时何时不对Swift中的委托指针使用"弱"赋值,为什么?
我的理解是,如果你使用一个未定义为类的协议,你不能也不想将你的委托指针指向weak.
protocol MyStructProtocol{
//whatever
}
struct MyStruct {
var delegate: MyStructProtocol?
}
Run Code Online (Sandbox Code Playgroud)
但是,当您的协议被定义为类类型协议时,您是否要将您的委托设置为弱指针?
protocol MyClassProtocol:Class{
//whatever
}
class MyClass {
weak var delegate: MyClassProtocol?
}
Run Code Online (Sandbox Code Playgroud)
我对么?在Apple的快速指南中,类协议示例并未使用弱分配,但在我的测试中,如果我的代表没有被弱引用,我会看到强大的引用周期.
Rob*_*Rob 44
您通常会将类协议(使用class
关键字定义)设置为弱,以避免出现"强参考周期"(以前称为"保留周期")的风险.未能使代表弱,并不意味着你本身就有一个强大的参考周期,而只是你可以拥有一个.
struct
但是,对于类型,强大的参考周期风险会大大减少,因为struct
类型不是"参考"类型,因此创建强大的参考周期更加困难.但是如果委托对象是一个类对象,那么您可能希望使协议成为类协议并使其变弱.
在我看来,让班级代表变弱只是为了减轻强大的参考周期的风险.这真的是一个"所有权"的问题.大多数委托协议都是这样的情况:有问题的对象没有业务声明对委托的所有权,而仅仅是有问题的对象提供了向委托人通知某事(或请求某些东西)的能力.
代表们(编辑:一般)应该总是很弱.
让我们说b
是代表a
.现在a
的delegate
财产是b
.
在一个情况下,你需要b
释放的时候c
是走了
如果c
拥有强大的引用b
和c
解除分配,则需要b
取消分配c
.然而,在使用一个强大的委托财产a
,b
永远不会释放,因为a
是抱着一种b
强烈.使用弱引用,一旦b
失去强引用c
,b
将在c
deallocs 时释放.
通常这是预期的行为,这就是您想要使用weak
属性的原因.
正如罗布所说:
这真的是一个“所有权”的问题
这是非常正确的。“强大的参考周期”就是获得所有权。
在以下示例中,我们没有使用weak var
. 然而,两个对象都将解除分配。为什么?
protocol UserViewDelegate: class {
func userDidTap()
}
class Container {
let userView = UserView()
let delegate = Delegate()
init() {
userView.delegate = delegate
}
deinit {
print("container deallocated")
}
}
class UserView {
var delegate: UserViewDelegate?
func mockDelegatecall() {
delegate?.userDidTap()
}
deinit {
print("UserView deallocated")
}
}
class Delegate: UserViewDelegate {
func userDidTap() {
print("userDidTap Delegate callback in separate delegate object")
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will deallocate both objects
Run Code Online (Sandbox Code Playgroud)
+---------+container +--------+
| |
| |
| |
| |
| |
| |
v v
userView +------------------> delegate
Run Code Online (Sandbox Code Playgroud)
为了创建一个强引用循环,循环需要是完整的。delegate
需要指向,container
但它没有。所以这不是问题。但纯粹出于所有权原因,正如 Rob 在这里所说的:
在对象层次结构中,子对象不应维护对父对象的强引用。那是一个危险信号,表示强引用循环
因此,无论泄漏如何,仍可weak
用于您的委托对象。
在以下示例中,我们没有使用weak var
. 结果,两个类都不会解除分配。
protocol UserViewDelegate: class {
func userDidTap()
}
class Container: UserViewDelegate {
let userView = UserView()
init() {
userView.delegate = self
}
func userDidTap() {
print("userDidTap Delegate callback by Container itself")
}
deinit {
print("container deallocated")
}
}
class UserView {
var delegate: UserViewDelegate?
func mockDelegatecall() {
delegate?.userDidTap()
}
deinit {
print("UserView deallocated")
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will NOT deallocate either objects
Run Code Online (Sandbox Code Playgroud)
+--------------------------------------------------+
| |
| |
+ v
container userview
^ |
| |
| |
+------+userView.delegate = self //container+------+
Run Code Online (Sandbox Code Playgroud)
使用weak var
将避免强引用循环