背景:回调机制中回调设置代码和回调方法的具体实现无法写在同一段代码中。Mac OS X 10.6和iOS4种引入了Block对象。Block对象看上去是一段代码,但是可以当作数据来传递。
定义Block对象:
^{
     NSLog(@“I’m a log statement within a block!");
}
这段代码看似是一个函数,但是没有函数名,相应的位置只有一个^符号,^符号表示这段代码是一个Block对象。与函数一样,Block对象也可以有实参:
^(double dividend,double divisor){
     double quotient = dividend / divisor;
     return quotient;
}
Block对象也可以有返回值。以上Block对象都只是值,没有名称。为了能够通过名称使用某个Block对象,就必须先将其赋值给Block对象变量。
使用Block对象:
block的变量声明如下
为Block变量赋值
Block变量的值一定是一段代码
声明和赋值也可以写在一起
typedef
可以用typedef将某个block对象定义为一个新类型,以方便使用。不能在方法的实现代码中使用typedef,应该在文件的顶部或者头文件内。
如,typedef void (^ArrayEnumerationBlock)(id, NSUInterger, BOOL *);
这里定义的是一个新的类型,而不是变量。跟在^字符后面的是类型名称。定义以后可以用ArrayEnumerationBlock devowelizer;这样声明普通变量那样声明Block对象。
返回值
对于有返回值的Block对象,可以像调用函数那样调用Block对象,然后使用其返回值。
double (^divBlock)(double,double) = ^(double k, double j ) {
     return k/j;
}
这段代码首先声明了一个名为divBlock的Block变量,然后将新创建的Block对象赋给了该变量。
Block对象divBlock的示例代码如:double quotient = divBlock(42.0,12.5);
 
内存管理:
Block对象也是在栈中创建并保存的,也就是说,当创建Block对象的函数或者方法完成执行并返回后,相应的Block对象会随着栈帧地释放而被释放。当需要继续保留Block对象时,必须将Block对象从栈靠背至堆。向Block对象发送copy消息可以将其从栈拷贝至堆。
ArrayEnumerationBlock iVarDevowelizer = [devowelizer copy];
iVarDevowelizer指向的对象是基于堆的Block对象,而不是基于栈的Block对象。
在将基于栈的Block对象拷贝至基于堆的Block对象时,Block对象会捕获其使用的变量。对基本类型的变量,捕获意味着程序会拷贝变量的值,并用Blok 参对象内的局部变量保存。对指针类型的变量,Block对象会使用strong特性的引用。这意味着凡是对Block对象用到的对象,都会被保留。
strong特性的引用有可能会导致retain循环问题。当 Block 对象所使用的对象保留了当前的Block 对象时,就会发生retain循环。解决途径:现在 Block对象外声明一个_weak指针,然后将这个指针指向Block 对象使用的对象,最后在 Block 对象中使用这个新的指针。
在 Block对象中,被捕获的变量是常数,程序无法修改变量所保存的值。需要在Block对象内修改某个外部变量,可以在声明相应的外部变量时,在前面加上_block关键字。例如,以下代码可以在Block对象内将外部变量counter的值增1。
_block int counter = 0;
void (^counterBlock)( ) = ^{ counter ++ };
...
counterBlock();//counter增1,数值为2
counterBlock();//counter增1,数值为2
如果这段代码没有使用_block关键字,那么编译器会在 Block 对象的定义处报错,提示修改counter值是无效的。
 

最新文章

  1. PHP的单态类——为了产生唯一的对象
  2. ruby -检查数据类型
  3. Orchard基本概念
  4. Sticky Footer (让页脚永远停靠在页面底部,而不是根据绝对位置)
  5. 【MariaDB】MariaDB编译参数
  6. loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
  7. Download Manager
  8. hdu5909-Tree Cutting(树形dp)
  9. UltraEdit 列模式
  10. NSDate与 NSString 、long long类型的相互转化
  11. 利用Advanced Installer将asp.netMVC连同IIS服务和mysql数据库一块打包成exe安装包
  12. 好代码是管出来的——浅谈.Net Core的代码管理方法与落地(更新中...)
  13. mssql sqlserver 自动备份存储过程的方法分享
  14. Kubernetes中的Configmap和Secret
  15. Hadoop2源码分析-YARN RPC 示例介绍
  16. HDU 1527 取石子游戏 (威佐夫博弈)
  17. 搞定queryString
  18. element-ui Pagination组件源码分析整理笔记(七)
  19. POJ2411骨牌覆盖——状压dp
  20. 正则表达式—RegEx(RegularExpressio)(三)

热门文章

  1. tab切换-淘宝案例
  2. Xcode真机调试出现The account '***' has no team with ID '***'的解决方案
  3. 设置java web工程中默认访问首页的几种方式
  4. 多线程完成socket
  5. 驱动插ring3线程执行代码
  6. Adapter 代码中启动报错
  7. 使用VMware Workstation 12.5.2新建虚拟机
  8. 开启关闭keditor 过滤
  9. Erlang&RabbitMQ服务安装配置
  10. __attribute__((packed))作用