2012-08-06 82 views
5

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]; 

爲什麼會產生第二個結果一個保留週期,但不是第一個?

+2

關鍵字是「保留CYCLE」。如同,我保留你,你保留我,所以誰先放手? – 2012-08-06 07:21:19

回答

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來中斷保留週期。

8

我不能告訴你在第二個例子中保留循環的原因,因爲我不知道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在塊執行時被釋放。

+0

如果塊被執行了,但它仍然保存在一些數組中,以便它可以再次使用?我猜自己不會在這裏被釋放,直到數組被清除? – Snowman 2012-08-06 15:34:51

+0

是的,我認爲這就是@robmayoff在他的回答中所描述的。 – 2012-08-06 15:42:36

+0

在塊內創建對弱(或者在我的情況下是__unsafe_unretained)指針的強引用解決了我在類中止塊中止時分配的類似問題。謝謝! – SRandazzo 2013-01-14 17:14:16