block小结

根据Block在内存中的位置分为三种类型NSGlobalBlockNSStackBlock, NSMallocBlock


NSGlobalBlock:们可以通过是否引用外部变量识别,未引用外部变量即为NSGlobalBlock,可以当做函数使用。


NSStackBlock:block的isa指向的不是object_class,而是_NSConcreteStackBlock,


NSMallocBlock:NSMallocBlock只需要NSStackBlock进行copy操作就可以获取,ARC下由于对象创建默认都是__strong类型的,因此创建block也一样,会直接在堆上创建,weak指针指向的block还在栈上


例如:

 NSString *string = @"test";
    
    void (^TestBlock)(void) = ^{
        
        NSLog(@"string :%@", string);
        
    };
    
    NSLog(@"block is %@", TestBlock);
    
    NSLog(@"block is %@", ^{
        
        NSLog(@"string :%@", string);
        
    });

ARC下打印信息如下:

2015-03-31 10:10:25.353 AppTest[3969:37015] block is <__NSMallocBlock__: 0x7fa8f0e79ed0>
2015-03-31 10:10:25.354 AppTest[3969:37015] block is <__NSStackBlock__: 0x7fff5a0caa28>


非ARC下打印信息如下:

2015-03-31 10:11:50.652 AppTest[4029:38035] block is <__NSStackBlock__: 0x7fff5d20fa38>
2015-03-31 10:11:50.653 AppTest[4029:38035] block is <__NSStackBlock__: 0x7fff5d20fa10>


非ARC下:


NSGlobalBlockretain无效,copy无效,release无效


NSStackBlock:retain无效,copy使NSStackBlock转化为NSMallocBlock,release无效


NSMallocBlock:retain使retainCount+1,copy使retainCount+1(不生成新对象),release使retainCount-1


ARC下:


当block作为参数返回的时候,block也会自动被移到堆上。

 

只要指针过一下strong指针,也会把block移动到堆上。


循环引用


block在拷贝到堆上的时候,retain其引用的外部变量,那么如果block中如果引用了他的宿主对象,那很有可能引起循环引用


解决方法:


In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.


参考资料:


http://www.cnblogs.com/hanjun/p/3767394.html

http://www.cocoachina.com/bbs/read.php?tid-152222-page-1.html

http://www.cocoachina.com/industry/20130605/6340.html


那个小测试的答案应该是:ABABA


例子2和4的非ARC下的解决方案就是将block对象copy到堆上来,记得要autorelease;

void exampleB_addBlockToArray(NSMutableArray *array) {
    char b = 'B';
    [array addObject:[[^{
        printf("%c\n", b);
    } copy] autorelease]];
}

例子5在非ARC下也是有问题的,连续两次调用block();就会崩溃,不知道为什么第一次调用没有崩溃,求解。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值