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