zoukankan      html  css  js  c++  java
  • Objective-C Blocks测试题与解析

    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.2
    Thread model: posix

    一下问题的选项是:都能工作;只在ARC下能工作;只在非ARC下能工作;不能执行

    Example A

    voidexampleA() {
      chara = 'A';
      ^{
        printf("%c ", a);
      }();
    }


    选择 always works.
    当block结束执行后exampleA的堆也不再继续。因此block被accocated在了
    堆上或者栈上,当执行时blocks才有效。

    Example B

    voidexampleB_addBlockToArray(NSMutableArray*array) {
      charb = 'B';
      [array addObject:^{
        printf("%c ", b);
      }];
    }
     
    voidexampleB() {
      NSMutableArray*array = [NSMutableArrayarray];
      exampleB_addBlockToArray(array);
      void(^block)() = [array objectAtIndex:0];
      block();
    }


    选择:只在ARC下能正常工作。
    不采用ARC的时候,block是一个在exampleB_addBlockToArray的栈上的NSStackBlock 。当exampleB执行的时候,block已经不存在,因为栈已经被释放。

    采用ARC机制时,block被实例化到了堆上是一个NSMallocBlock,采用自动释放方法。

    Example C

    voidexampleC_addBlockToArray(NSMutableArray*array) {
      [array addObject:^{
        printf("C ");
      }];
    }
     
    voidexampleC() {
      NSMutableArray*array = [NSMutableArrayarray];
      exampleC_addBlockToArray(array);
      void(^block)() = [array objectAtIndex:0];
      block();
    }
    选择always works.

    因为block中没有引用任何变量,他在执行时不需要任何声明,它被编译成了一个NSGlobalBlock。它既不在堆上又不在栈上。有点像c中的函数

     在有没有ARC下都可以工作。

    Example D

    typedefvoid(^dBlock)();
     
    dBlock exampleD_getBlock() {
      chard = 'D';
      return^{
        printf("%c ", d);
      };
    }
     
    voidexampleD() {
      exampleD_getBlock()();
    }


    选择 only works with ARC.

    它和 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 ", e);
      };
      returnblock;
    }
     
    voidexampleE() {
      eBlock block = exampleE_getBlock();
      block();
    }
    选择 only works with ARC.

    和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 into arrayWithObjects: and other methods that do a retain.

    原文译自http://blog.parse.com/2013/02/05/objective-c-blocks-quiz/。。不对之处各位大神请指正。新浪微博@WildCat李兴乐点击打开链接

  • 相关阅读:
    如果你想开发一个应用(1-17)
    如果你想开发一个应用(1-16)
    如果你想开发一个应用(1-15)
    0079 Ehcache 3.x应用入门及通过JCache与Spring整合
    0078 Java与MySQL时间戳传递/存储/协调问题--userLegacyDatetimeCode--userTimezone--serverTimezone
    0077 web.xml中配置Spring MVC时,Servlet-name上报Servlet should have a mapping的错误
    0076 判断回文串
    0075 字符串的反转
    0074 几道面试题
    0073 javacTask: 源发行版 1.8 需要目标发行版 1.8
  • 原文地址:https://www.cnblogs.com/lixingle/p/3707690.html
Copyright © 2011-2022 走看看