注意block中变量捕捉的问题

用block可以定义任意的代码片段,将其像对象一样传入另一个方法;它是c级别的语法,和C语言中的函数指针非常相似。在C语言中,函数指针和block写法分别如下

  int  (* func1)( int  a,  int  b); //c函数指针
返回类型 | 函数名 | 参数

int (^backValue)(intnum);//block
返回类型 | 方法名 参数

从表面来看两者唯一的区别就在于*和^。通常来说,block都是一些简短代码片段的封装,适用做工作单 元,通常用来做并发任务、遍历以及回调。block对象也是对象,实例化方法如下
int  (^backValue)( int ) = ^( int  num) {
     return  num+ 1 ;
};
block需要注意的一个特性就是"Variable Capturing",直译过来就是捕捉变量。block会将“捕捉”到的变量复制一份,然后对复制品进行操作,这是非常重要的一点。对于以下代码来说打印结果是b-->2,这是因为在block作用域内会复制a,然后对复制的a进行操作,作用域外的a就不会产生变化,所以,在a++;之后再调用backValue(1),结果是2
int a = 1;
int  (^backValue)( int ) = ^( int  num) {
     return  num+a;
};
a +=  1 ;
int  b = backValue( 1 );
NSLog(@ "b-->%d" , b);
如果希望block作用域内可以修改外边的变量,可以使用__block(注意是两个下划线)来修饰int a。这样以来结果就会是b-->3。

刚才的例子中a是一个基本类型的变量,如果block外是一个oc对象的话,结果就又不一样了,比如下边代码,结果就是"block作用域内赋值"
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake( 10 ,  300 ,  300 , 40 )];
label.text = @ "block作用域外赋值" ;
void  (^backValue)(NSString *) = ^(NSString *str) {
     label.text = str;
};
backValue(@ "block作用域内赋值" );
[self.view addSubview:label];
这是因为UILabel *label;定义了一个对象指针,在block作用域内复制的是label这个指针,而不是对象,复制之后的指针仍然指向原来的对象,所以对label.text进行操作是可以修改原对象的,但是作用域内如果想下边这样写就不行了,会得到提示Variable is not assignable。
label = [[UILabel alloc] init];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值