In this question,我询问了以下代码并保留了周期:
__weak Cell *weakSelf = self;
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
UIImage *image = /* render some image */
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[weakSelf setImageViewImage:image];
}];
}];
[self.renderQueue addOperation:op];
所有答案都指出在这里使用弱引用不是必需的,因为此代码不会导致保留周期。但是,在尝试更多代码时,以下操作会导致保留周期(如果我不使用弱引用,则不会释放当前视图控制器)
//__weak ViewController *weakSelf = self;
MBItem *close = [[MBItem alloc] initWithBlock:^{
[self dismissModalWithDefaultAnimation:NO];
}];
NSMutableArray *items = [[NSMutableArray alloc] initWithObjects:close, nil];
[self.childObject setItems:items];
为什么第二个会导致保留周期而不是第一个?
答案 0 :(得分:12)
如果您不使用__weak
,旧代码会创建此保留周期:
(NSBlockOperation *)op
保留外部块self
(如果您未使用__weak
)self
保留(NSOperationQueue *)renderQueue
(NSOperationQueue *)renderQueue
保留(NSBlockOperation *)op
除非其中一个链接被破坏,否则该循环中的所有对象都不能被释放。但是,您向我们展示的代码确实打破了保留周期。当op
完成执行时,renderQueue
会释放它,从而打破保留周期。
我怀疑您的新代码会创建此保留周期:
(MBItem *)close
保留了阻止self
self
保留childObject
childObject
保留(NSMutableArray *)items
(NSMutableArray *)items
保留(MBItem *)close
如果没有任何事情可以破坏其中一个链接,则循环中的所有对象都不能被释放。您没有向我们展示任何打破保留周期的代码。如果没有明确破坏它的事件(例如清除childObject.items
),则需要使用__weak
来中断保留周期。
答案 1 :(得分:8)
我无法告诉你第二个例子中保留周期的原因,因为我不知道MBItem
,但是有两种不同的使用模式。
如果您希望您的块在任何情况下都可以执行,那么您可以在块中使用self
:
[startSomeOperationWithCompletionBlock:^{
[self doSomeThing];
}];
该块保留对self
的引用,以便在执行块之前不释放self
。但是在块执行之后,这个引用(以及保留周期)就消失了。
如果您希望在块执行之前取消分配{strong> <{1}}, 或者如果有可能根本不会调用该块, 那么你必须使用弱引用并检查块内的值:
self
在这种情况下,块不会保留__weak MyClass *weakSelf = self;
[startSomeOperationWithCompletionBlock:^{
MyClass *strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomeThing];
}
}];
,因此可以释放self
。在这种情况下,self
会自动设置为weakSelf
。因此,如果最后执行该块,则必须首先检查nil
是否仍然有效。 (或者您可以使用它,因为向weakSelf
发送消息是无操作。)
在块内部分配强引用nil
可防止在块执行时释放strongSelf
。