Objective-C Blocks测试题与解析
2014-04-11 17:35 Lves Li 阅读(436) 评论(0) 收藏 举报Objective-C Blocks 测试
你真的理解blocks在objective-c中是如何工作的了吗,做个测试检验一下吧。
所有的测试结果已被以下版本的LLVM验证:
| Apple
 clang version 4.1 (tags/Apple/clang-421.11.66)
 (based on LLVM 3.1svn)Target:
 x86_64-apple-darwin11.4.2Thread
 model: posix | 
一下问题的选项是:都能工作;只在ARC下能工作;只在非ARC下能工作;不能执行
Example A
| voidexampleA()
 {  chara
 = 'A';  ^{    printf("%c\n",
 a);  }();} | 
Example B
| voidexampleB_addBlockToArray(NSMutableArray*array)
 {  charb
 = 'B';  [array
 addObject:^{    printf("%c\n",
 b);  }];}voidexampleB()
 {  NSMutableArray*array
 = [NSMutableArrayarray];  exampleB_addBlockToArray(array);  void(^block)()
 = [array objectAtIndex:0];  block();} | 
exampleB_addBlockToArray的栈上的NSStackBlock 。当exampleB执行的时候,block已经不存在,因为栈已经被释放。采用ARC机制时,block被实例化到了堆上是一个NSMallocBlock,采用自动释放方法。
Example C
| voidexampleC_addBlockToArray(NSMutableArray*array)
 {  [array
 addObject:^{    printf("C\n");  }];}voidexampleC()
 {  NSMutableArray*array
 = [NSMutableArrayarray];  exampleC_addBlockToArray(array);  void(^block)()
 = [array objectAtIndex:0];  block();} | 
因为block中没有引用任何变量,他在执行时不需要任何声明,它被编译成了一个NSGlobalBlock。它既不在堆上又不在栈上。有点像c中的函数
在有没有ARC下都可以工作。
Example D
| typedefvoid(^dBlock)();dBlock
 exampleD_getBlock() {  chard
 = 'D';  return^{    printf("%c\n",
 d);  };}voidexampleD()
 {  exampleD_getBlock()();} | 
它和 example B类似。不采用ARC, block 将会创建在exampleD_getBlock 的栈上当函数返回时就无效了。在这种情况下,编译器会报以下的错误 error:
 returning block that lives on the local stack.
采用ARC block会被编译成一个自动释放的 NSMallocBlock.
Example E
| typedefvoid(^eBlock)();eBlock
 exampleE_getBlock() {  chare
 = 'E';  void(^block)()
 = ^{    printf("%c\n",
 e);  };  returnblock;}voidexampleE()
 {  eBlock
 block = exampleE_getBlock();  block();} | 
和example D类似, 这段代码会正常编译,运行时会崩溃。更糟的情况是,如果你不检查,测试时他可能运行正常,在项目中就会崩溃。
采用ARC block会被编译成一个自动释放的 NSMallocBlock.
总结
考虑一下关键点是什么?总是采用ARC嘛。采用ARC它总能运行正常. 如果你不采用ARC, 你最好这样做 block
 = [[block copy] autorelease] 。 这样强制编译器深拷贝成一个 NSMallocBlock。
哈哈,它当然远没有这么简单。苹果官网是这么提示的:
Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use[^{} copy]when passing “down” the stack intoarrayWithObjects:and other methods that do a retain.
原文译自http://blog.parse.com/2013/02/05/objective-c-blocks-quiz/。。不对之处各位大神请指正。新浪微博@WildCat李兴乐点击打开链接
 
                    
                     
                    
                 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号