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\n",
a);
  }();
}

always works. 
only works with ARC. only works without ARC. 
never works.

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

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();
}

always works. only works with ARC.
 only works without ARC. 
never works.

选择:只在ARC下能正常工作。
不采用ARC的时候,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();
}

always works. only works with ARC.
 only works without ARC. 
never works.

选择always works.

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

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

Example D

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

always works. only works with ARC.
 only works without ARC. 
never works.

选择 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\n",
e);
  };
  returnblock;
}
 
voidexampleE()
{
  eBlock
block = exampleE_getBlock();
  block();
}

always works. only works with ARC.
 only works without ARC. 
never works.

选择 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李兴乐点击打开链接

Objective-C Blocks测试题与解析的更多相关文章

  1. PHP基础知识测试题及解析

      本试题共40道选择题,10道判断题,考试时间1个半小时 一:选择题(单项选择,每题2分): 1. LAMP具体结构不包含下面哪种(A ) A:Windows系统 B:Apache服务器 C:MyS ...

  2. Objective-C 与 C++ 的异同

    stackflow 上有同学提问"C++ 与 Objective-C 有什么异同?"楼下的提供的两个资料挺不错的. 其一是: Pierre Chatelier 写的 <Fro ...

  3. MIT jos 6.828 Fall 2014 训练记录(lab 5)

    源代码参见我的github: https://github.com/YaoZengzeng/jos File system perliminaries 我们开发的是一个单用户的操作系统,只提供了足够的 ...

  4. Cheatsheet: 2013 08.01 ~ 08.13

    Mobile Objective C Blocks: Summary, Syntax & Best Practices Android SDK: Create an Arithmetic Ga ...

  5. iOS 常见 Crash 及解决方案

    一.访问了一个已经被释放的对象 在不使用 ARC 的时候,内存要自己管理,这时重复或过早释放都有可能导致 Crash. 例子 NSObject * aObj = [[NSObject alloc] i ...

  6. 玩转webpack(二):webpack的核心对象

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者介绍:陈柏信,腾讯前端开发,目前主要负责手Q游戏中心业务开发,以及项目相关的技术升级.架构优化等工作. 前言 webpack 是一个强大的模 ...

  7. SoftwareEngineering.APIDesign.iOS

    API Design for iOS/Mac (Objective-c Edition) 1. UI Control Library API的设计 和已有组件保持一致(例如: 使用标准的API, 模型 ...

  8. C,OC,C++语言对比

    1.C与OC.C++的区别: C语言的特点:面向过程 1)C语言是结构化语言,层次清晰,调试和维护比较容易 2)表现能力和处理能力比较强,可直接访问内存的物理地址 3)c语言实现对硬件的编辑,c语言课 ...

  9. Clang:LLVM的C语言家族前端

    Clang:LLVM的C语言家族前端 Clang项目为LLVM 项目的C语言家族(C,C ++,Objective C / C ++,OpenCL,CUDA和RenderScript)中的语言提供了语 ...

随机推荐

  1. 找呀志_使用SQLiteDatabase增删改提供的搜索方法和事务

    知识具体解释:http://blog.csdn.net/zhaoyazhi2129/article/details/9026093 MainActivity.java,User.java,BaseDa ...

  2. hibernate tools连接数据报错

    报如下的错误: An internal error occurred during: "Fetching children of Database". org.slf4j.spi. ...

  3. 关于JavaScript中计算精度丢失的问题

    摘要: 由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而JavaScript中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失. 为了避免产生精度差异,把需要计算的数字升级(乘 ...

  4. php_PHP与Mysql的连接

    展示效果: 繁写: <?php    echo "This is a test</br>";     echo "asdfasdfadsf"; ...

  5. DFGUI-- 标签交换 Tabstrip

    DFGUI没有更新,事实上,有些遗憾. 它着重于一个小 Examples/Containers/TabContainer.unity 那是,Tab采用. 功能 非常easy.就是切换Tag 内容改变. ...

  6. ionic入门之基本布局

    目录: 简介 Hybrid vs. Others ionic CSS框架 基本布局 布局模式 定高条块:.bar .bar : 位置 .bar : 嵌入子元素 .bar : 嵌入input 内容:.c ...

  7. LeetCode——Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  8. Visual Studio 2015环境

    Visual Studio 2015环境搭建 2014年11月13日,微软发布了Visual Studio 2015 Preview,跟随者Visual Studio 2015 而来的是,.net 开 ...

  9. PCL点云库中怎样读取指定的PCD文件,又一次命名,处理后保存到指定目录

    我一直想把处理后的pcd文件重命名,然后放到指定的目录,尝试了好久最终做到了: 比方我想读取  "table_scene_lms400.pcd" 把它进行滤波处理,重命名为 &qu ...

  10. HBuilder HTML 自定义代码块

    =begin 本文档是HTML代码块的编辑文件.注意不要把其他语言的设置放到html里来. HBuilder可使用ruby脚本来编辑代码块和增强操作命令. 1.编辑代码块 如果要新增一个代码块,复制如 ...