簡體   English   中英

塊中的弱引用和保留周期

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM