您不需要使所有内容变弱,也不需要继续引用块中的弱对象(特别是如果块可以在不同的线程中执行)。
这样想吧。使用 ARC 时,对象被引用计数。在引用计数变为零之前,不会对对象调用 dealloc。因此,只要周围有一个引用,对象就会保持活动状态。
但是,请考虑两个相互具有强引用的对象。在另一个释放其引用之前,两者都不会释放。
创建块时,它会捕获其环境,这意味着它将创建对块范围内使用的任何对象的强引用。
考虑到这一点...
id object = getMeSomeObject();
// <object> is implicitly __strong, and now has a reference.
在释放所有强引用之前,该对象不会被释放。如果在块中使用它,块会自动创建自己的强引用,以确保对象与块一样长。
__weak 引用是一种间接级别,它使您可以在对象存在时访问对象。基本上,如果您将一个对象分配给一个 __weak 指针,只要该对象是活动的,该指针就可以保证为您提供相同的对象。一旦对象启动它自己的 dealloc(),它就会找到所有的 __weak 指针并将它们设置为 nil。
因此,您的 _weak 指针将始终处于两种状态之一。只要对象存在,它就指向一个有效的对象,或者当对象具有 dealloc 时它是 nil。你永远不应该通过弱指针访问一个对象,因为这个对象可能会在你背后释放,给你留下一个坏指针。
所以,你想要做的是在堆栈上创建一个 __strong 引用,以便对象只要你想要它就保持活动状态。
在你的情况...
[_request setCompletionBlock:^{
[self setResponseString:_request.responseString];
[[MyAppDelegate getQueue] addOperation:_operation];
}];
这个块显然对self
. 你可能不希望那样。让我们尝试修复它...
// weakSelf will be "magically" set to nil if <self> deallocs
__weak SelfType *weakSelf = self;
[_request setCompletionBlock:^{
// If <self> is alive right now, I want to keep it alive while I use it
// so I need to create a strong reference
SelfType *strongSelf = weakSelf;
if (strongSelf) {
// Ah... <self> is still alive...
[strongSelf setResponseString:_request.responseString];
[[MyAppDelegate getQueue] addOperation:_operation];
} else {
// Bummer. <self> dealloc before we could run this code.
}
}];
嘿,我们现在有一个 weak self
,但是......你仍然会遇到同样的问题。为什么?因为 _request 和 _operation 是实例变量。如果您访问块内的实例变量,它会隐式创建对self
.
再给它一次...
// weakSelf will be "magically" set to nil if <self> deallocs
__weak SelfType *weakSelf = self;
[_request setCompletionBlock:^{
// If <self> is alive right now, I want to keep it alive while I use it
// so I need to create a strong reference
SelfType *strongSelf = weakSelf;
if (strongSelf) {
// Ah... <self> is still alive...
[strongSelf setResponseString:strongSelf->_request.responseString];
[[MyAppDelegate getQueue] addOperation:strongSelf->_operation];
} else {
// Bummer. <self> dealloc before we could run this code.
}
}];
现在,您可能不应该在“原始”中使用实例变量,但这是一个不同的主题。
通过这些更改,您将拥有一个不再对 self 有强引用的块,如果self
确实进行了释放,它会优雅地处理它。
最后,我要重申,给 strongSelf 赋值是必要的,以防止在检查 weakSelf 后对象消失的潜在问题。具体来说...
if (weakSelf) {
// Hey, the object exists at the time of the check, but between that check
// and the very next line, its possible that the object went away.
// So, to prevent that, you should ALWAYS assign to a temporary strong reference.
[weakSelf doSomething];
}
strongSelf = weakSelf;
// OK, now IF this object is not nil, it is guaranteed to stay around as long as
// strongSelf lives.
现在,在这种情况下,块是请求的一部分,这是deallocsself
的可能性self
很小的一部分,但我这里的主要观点是使用self来防止保留循环,但仍然始终通过强引用访问对象——弱强舞。