《Objective-C高级编程》Blocks 阅读笔记系列
《Objective-C高级编程》Blocks 阅读笔记 item1(Blocks概要和模式)
《Objective-C高级编程》Blocks 阅读笔记 item2(Block的实质)
《Objective-C高级编程》Blocks 阅读笔记 item3(截获自动变量值)
《Objective-C高级编程》Blocks 阅读笔记 item4(__block说明符)
《Objective-C高级编程》Blocks 阅读笔记 item5(Block存储域)
《Objective-C高级编程》Blocks 阅读笔记 item6(__block变量存储域)
《Objective-C高级编程》Blocks 阅读笔记 item7(截获对象)
《Objective-C高级编程》Blocks 阅读笔记 item8(__block变量和对象)
《Objective-C高级编程》Blocks 阅读笔记 item9(Block循环引用)
《Objective-C高级编程》Blocks 阅读笔记 item10(copy/release实例方法)
2.3 Blocks的实现
2.3.9 copy/release
*** ARC无效时,需要用copy实例方法手动将Blocl从栈复制到堆,用release实例方法来释放复制的Block。 ***
void (^blk_on_heap)(void) = [blk_on_stack copy];
[blk_on_heap release];
*** 只要Block有一次复制并配置在堆上,就可通过retain实例方法持有。***
[blk_on_heap retain];
*** 但是,对于配置在栈上的Block调用retain实例方法则不起任何作用。 ***
[blk_on_stack retain];
该源代码中,虽然对赋值给blk_on_stack的栈上的Block调用了retain实例方法,但实际上对此源代码不起任何作用。因此,推荐使用copy实例方法来持有Block(不用retain实例方法)。
由于Block是C语言的扩展,所以在C语言中也可以使用Block语法。此时使用“Block_copy函数”和“Block_release函数”代替copy/release实例方法。
void (^blk_on_heap)(void) = Block_copy(blk_on_stack);
Block_release(blk_on_heap);
*** ARC无效时,__block说明符被用来避免Block中的循环引用。***
这是由于当Block从栈复制到堆时,若Block使用的变量为附有__block说明符的id类型或对象类型的自动变量,不会被retain;若Block使用的变量为没有__block说明符的id类型或对象类型的自动变量,则被retain。
typedeft void (^blk_t)(void);
@interface MyObject : NSObject
{
blk_t blk_;
}
@end
@implementation MyObject
- (id)init
{
self = [super init];
blk_ = ^{NSLog(@"self = %@", self);};
return self;
}
- (void)dealloc
{
NSLog(@"dealloc");
}
@end
int main()
{
id o = [[MyObject alloc] init];
NSLog(@"%@", o);
return 0;
}
该源代码无论ARC有效还是无效都会引起循环引用,Block持有self,self持有Block。
可使用__block变量来避免出现该问题。
- (id)init
{
self = [super init];
__block id blockSelf = self;
blk_ = ^{NSLog(@"self = %@", blockSelf);};
return self;
}
这时,由于Block使用__block变量,所以不会被retain。
注意
- ARC有效时,__block说明符和__unsafe_unretained修饰符一起使用,来解决附有__unsafe_unretained修饰符的自动变量不能retain的问题。
- __block说明符在ARC有效无效时的用途有很大的区别,所以,在使用__block说明符必须清楚源代码是在ARC有效还是无效的情况下编译。
网友评论