你真的知道blocks在Objective-C中是怎么工作的吗?

2 篇文章 0 订阅

关键提示:你首先需要搞清楚这个block是分配在哪里的内存,NSMallocBlock,NSStackBlock,NSGlobalBlock,然后再判断arc和非arc状态下的区别,祝你好运哦,亲。---likendsl 


例子1

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. void exampleA() {  
  2.   chara = 'A';  
  3.   ^{  
  4.     printf("%c\n", a);  
  5.   }();  
  6. }  
这个例子:

A.始终能够正常运行                B.只有在使用ARC的情况下才能正常运行
C.不使用ARC才能正常运行   D.永远无法正常运行


例子2:

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. void exampleB_addBlockToArray(NSMutableArray *array) {  
  2.   charb = 'B';  
  3.   [array addObject:^{  
  4.     printf("%c\n", b);  
  5.   }];  
  6. }  
  7.     
  8. void exampleB() {  
  9.   NSMutableArray*array = [NSMutableArrayarray];  
  10.   exampleB_addBlockToArray(array);  
  11.   void(^block)() = [array objectAtIndex:0];  
  12.   block();  
  13. }  

 

A.始终能够正常运行                B.只有在使用ARC的情况下才能正常运行

C.不使用ARC才能正常运行   D.永远无法正常运行

例子3

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. void exampleC_addBlockToArray(NSMutableArray *array) {  
  2.   [array addObject:^{  
  3.     printf("C\n");  
  4.   }];  
  5. }  
  6.     
  7. void exampleC() {  
  8.   NSMutableArray*array = [NSMutableArrayarray];  
  9.   exampleC_addBlockToArray(array);  
  10.   void(^block)() = [array objectAtIndex:0];  
  11.   block();  
  12. }  

A.始终能够正常运行                B.只有在使用ARC的情况下才能正常运行
C.不使用ARC才能正常运行   D.永远无法正常运行


例子4
[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. typedef void (^dBlock)();  
  2.     
  3. dBlock exampleD_getBlock() {  
  4.   chard = 'D';  
  5.   return^{  
  6.     printf("%c\n", d);  
  7.   };  
  8. }  
  9.     
  10. void exampleD() {  
  11.   exampleD_getBlock()();  
  12. }  

A.始终能够正常运行                B.只有在使用ARC的情况下才能正常运行
C.不使用ARC才能正常运行   D.永远无法正常运行



例子5
[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. typedef void (^eBlock)();  
  2.     
  3. eBlock exampleE_getBlock() {  
  4.   chare = 'E';  
  5.   void(^block)() = ^{  
  6.     printf("%c\n", e);  
  7.   };  
  8.   returnblock;  
  9. }  
  10.     
  11. void exampleE() {  
  12.   eBlock block = exampleE_getBlock();  
  13.   block();  
  14. }  

A.始终能够正常运行              B.只有在使用ARC的情况下才能正常运行
C.不使用ARC才能正常运行   D.永远无法正常运行


答案
例子1

A正确 。这个例子可以正常运行。储存exampleA的栈只有在block停止执行之后才会释放,因此,无论此Block由系统分配到栈中还是我们自己手动分配到堆中,它都可以正常执行。


例子2

B正确 。如果不使用ARC,这个block是一个NSStackBlock,分配给exampleB_addBlockToArray的栈上。而当它在exampleB中执行的时候,由于栈被清空,block不再有效。

而使用ARC的话,block会分配到堆中,作为一个自动释放的NSMallocBlock


例子3

A正确

由于block在自己的环路中不会抓取任何变量,它不需要在在运行的时候设置state,它会作为一个NSGlobalBlock编译。它既不是栈也不是堆,而是代码片段的一部分。所以它始终都能正常运行。


例子4

B正确 。这个例子和例子2类似。如果不使用ARC,block会在exampleD_getBlock的栈上创建起来。然后当功能返回的时候会立即失效。

然而,以这个例子来说,这个错误非常明显,所以编译器进行编译会失败,错误提示是:error: returning block that lives on the local stack(错误,返回的block位于本地的栈)。


例子5

B正确 。这个例子和例子4类似,除了编译器没有认出有错误,所以代码会进行编译然后崩溃。更糟糕的是,这个例子比较特别,如果你关闭了优化,则可以正常运行。所以在测试的时候需要注意。

而如果使用ARC的话,block则会正确的位于堆上,作为一个自动释放的NSMallocBlock。


结论
这套小测试有什么意义呢?意义就是要一直使用ARC。使用ARC,block大部分情况下都可以正常运行。

如果不使用ARC,谨慎起见,可以block = [[block copy] autorelease],这样block会比申明它的栈flame的有效期长。这样block会被作为一个NSMallocBlock强制复制到堆上。

但是,当然不会这么简单,根据苹果的文档,

Block只有当你在ARC模式下传递block到栈上才会工作,比如说返回的时候。你不需要再次调用Block Copy了。但是当block从栈上传递到 arrayWithObjects: 和其他做了一个retain的方法是时,仍然需要使用[^{} copy]。


但是有一个LLVM的维护者之后也说过:

我们认为这是编译器的bug,它现在已经修复了。但是Xcode以后是否会在以后发布的新版本中解决这个问题,我也不知道。


所以,希望,苹果也把它认为是一个bug,在以后的新版本中会解决这个问题。让我们看看会怎么样吧
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值