关于block和引用计数

(1)修饰block
如果需要block在它被声明的作用域被销毁后继续使用的话,你就需要做一份拷贝。拷贝会把block移到堆里面。所以,使用@property时设置通常如下:
@property(copy, nonatomic)void(^block)(void);

(2)retain cycle的问题
block在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在block块内使用该只读拷贝。所以在使用block过程中,经常会遇到retain cycle的问题,例如:

1 - (void)dealloc
2 {
3 [[NSNotificationCenter defaultCenter] removeObserver:_observer];
4 }
5 - (void)loadView
6 {
7 [super loadView];
8
9 _observer = [[NSNotificationCenterdefaultCenter] addObserverForName:@”testKey”
10 object:nil
11 queue:nil
12 usingBlock:^(NSNotification*note)
13 {
14 [sselfdismissModalViewControllerAnimated:YES];
15 }];
16 }
在block中用到了self,self会被block retain,而_observer会copy一份该block,就是说_observer间接持有self,同时当前的self也会retain_observer,最终导致self持有_observer,_observer持有self,形成retaincycle。
对于在block中的retain cycle,在2011 WWDC Session #322 (Objective-C Advancements in Depth)有一个解决方案weak-strong dance,其实现如下:

1 - (void)dealloc
2 {
3 [[NSNotificationCenter defaultCenter] removeObserver:_observer];
4 }
5 - (void)loadView
6 {
7 [super loadView];
8
9 __weakTestViewController *wself =self;
10 _observer =[[NSNotificationCenter defaultCenter] addObserverForName:@”testKey”
11 object:nil
12 queue:nil
13 usingBlock:^(NSNotification *note)
14 {
15 TestViewController *sself = wself;
16 [sselfdismissModalViewControllerAnimated:YES];
17 }];
18 }
在block中使用self之前先用一个__weak变量引用self,导致block不会retain self,打破retain cycle,然后在block中使用wself之前先用__strong类型变量引用wself,以确保使用过程中不会dealloc。简而言之就是推迟对self的retain,在使用时才进行retain。

(3)return一个block
返回一个block时,ARC会自动将block加上autorelease,所以需要注意,如果执行过程中不能接受在runloop接受后才释放block,就需要自己加入@autoreleasepool块,但是测试发现64位iOS/mac时,系统会自动在使用结束后立即释放,32位则要等到runloop结束。
1 - (void)test
2 {
3 //@autoreleasepool{
4 AutoTest *a = [AutoTestsAutoTest];
5 NSLog(@“1”);
6 a = nil;
7 NSLog(@”2”);
8 a = [[AutoTest alloc] init];
9 //}
10 NSLog(@”3”);
11 }
12 - (IBAction)ok:(id)sender
13 {
14 [self test];
15 NSLog(@”4”);
16 }

//执行结果

1释放23释放4 64位
123释放4释放 32位
12释放释放34 32位+@autoreleasepool

(4)block作为参数
block作为参数时,如果使用范围超过了block的作用域(比如异步时,或者将block传递给其他对象等等),则需要copy此block,copy建议在使用此block的方法内实现(谁使用,谁管理),而不是在传递参数时copy。注意,block过一个strong类型的指针时,会自动copy。经过copy过的block会从栈空间移动到堆上,并且,copy一个已经在堆上的block时,此block不会受影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值