我有一个块保留周期问题,
假设我有以下3种方法,都在一个类中。
- (void)foo1WithBlock:(void (^)(BOOL success))completion
// do something...
completion(YES)
}
- (void)foo2 {
// do something...
}
- (void)foo3 {
[self foo1WithBlock:^(BOOL success) {
[self foo2];
}];
}
foo3会创建一个保留周期吗?
答案 0 :(得分:9)
不,没有保留周期。
但是,self
将捕获。这意味着, self 将导入到复合语句的词法范围内(由块执行的语句)。这涉及制作“外部”变量self
的副本,该变量创建块的变量self
。
可以复制和释放。 block_copy
操作会将捕获的变量“移动”到堆上。它们存在于那里,直到块通过block_release
操作被销毁。编译器/运行时提供内部函数来复制和释放块,并在需要时执行它们。例如,如果通过dispatch_async()
异步执行块,则必须首先复制块,然后在块完成后再次释放。这些block_copy
和block_release
操作由编译器插入并由运行时执行,因此请不要担心。
如果要复制该块,则会保留效果self
,并在块被释放时再次释放 - 这在块完成时会发生。
实际上,这可以保证块中的self
和块的生命周期内的self
是有效的(也就是说,它不会被释放),无论是同步调用还是异步调用。当块已异步执行时,块已被复制,因此保留了self
。并且self
将仅在块完成之后再次释放。这也意味着,块“将”延长{{1}}的生命期,直到块完成为止。
答案 1 :(得分:0)
不,没有保留周期......因为你没有在这里调用其他方法。
答案 2 :(得分:-1)
- (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];
}];
}