簡體   English   中英

目標c - 阻止保留周期

[英]objective c - block retain cycle

我有一個塊保留周期問題,
假設我有以下3種方法,都在一個類中。

- (void)foo1WithBlock:(void (^)(BOOL success))completion
   // do something...
   completion(YES)
}  

- (void)foo2 {
   // do something...
}  

- (void)foo3 {
   [self foo1WithBlock:^(BOOL success) {
       [self foo2];
   }]; 
}

foo3會創建一個保留周期嗎?

不,沒有保留周期。

但是, self將被捕獲 這意味着, self將被導入復合語句的詞法范圍(由塊執行的語句)。 這涉及制作“外部”變量self的副本,該副本創建塊的變量self

可以復制釋放塊。 block_copy操作將捕獲的變量“移動”到堆上。 它們存在於那里,直到塊通過block_release操作被銷毀。 編譯器/運行時提供內部函數來復制和釋放塊,並在需要時執行它們。 例如,如果該塊被經由異步執行dispatch_async()的塊將必須首先被復制 ,后來當塊完成時,再次釋放 這些block_copyblock_release操作由編譯器插入並由運行時執行,因此不必擔心。

如果塊將被復制,則作為一個效果self將被保留,並在塊被釋放時再次釋放 - 這在塊完成時發生。

實際上,這可以保證塊內的self和塊的生命周期內的self是有效的(也就是說,它不會被釋放),無論是同步調用還是異步調用。 當塊已異步執行時,塊已被復制,因此保留了self 只有在完成后, self才會被釋放。 這也意味着,塊“將”延長self的生命期,直到塊結束。

不,沒有保留周期......因為你沒有在這里調用彼此的方法。

- (void)foo3 {
   [self foo1WithBlock:^(BOOL success) {
       [self foo2];
   }]; 
}

在這種情況下,如果你不理解你傳遞給foo1WithBlock的塊的生命周期:使用這個成語可能是一個好主意,以防止塊不適當地延長self的生命周期。

- (void)foo3 {
   __weak ParentType *wself = self;  //create a weak reference (weak automatically gets set to nil on dealloc)
   [self foo1WithBlock:^(BOOL success) {
       ParentType *self = wself;  //create a local strong reference for the life of the block.
       [self foo2];
   }]; 
}

如果您正在使用cocoapods,libextobjc有一個EXTScope,它為此提供了幫助宏:

- (void)foo3 {
   @weakify(self);
   [self foo1WithBlock:^(BOOL success) {
       @strongify(self);
       [self foo2];
   }]; 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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