[英]Weak references in blocks and retain cycles
在這個問題中 ,我詢問了以下代碼並保留了周期:
__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];
為什么第二個會導致保留周期而不是第一個?
如果不使用__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
來打破保留周期。
我不能告訴你第二個例子中保留周期的原因,因為我不知道MBItem
,但是有兩種不同的使用模式。
如果您希望您的塊在任何情況下都可以執行,那么您可以在塊中使用self
:
[startSomeOperationWithCompletionBlock:^{
[self doSomeThing];
}];
該塊保留對self
的引用,因此在執行塊之前不會釋放self
。 但是塊執行后,此引用(以及保留周期)消失了。
如果您可能希望在執行塊之前釋放self
,或者可能根本不調用該塊,則必須使用弱引用並檢查塊內的值:
__weak MyClass *weakSelf = self;
[startSomeOperationWithCompletionBlock:^{
MyClass *strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomeThing];
}
}];
在這種情況下,塊不保留self
,因此可以釋放self
。 在這種情況下, weakSelf
會自動設置為nil
。 因此,如果最后執行該塊,則必須首先檢查weakSelf
是否仍然有效。 (或者你可以使用它,因為向nil
發送消息是無操作的。)
在塊中分配強引用strongSelf
可防止在塊執行時釋放self
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.