Block : 带有自动变量(局部变量)的匿名函数。
Block作用 : 用来保存一段代码,可以在适当的时候调用
Block实质 : 结构体,其里面有一个函数指针
Block应用场景 : 动画、多线程、集合遍历、网络请求回调
Block格式 : ^返回值类型 参数列表 {表达式} (如果返回值类型为void和参数列表为空时是可以省略不写的)
Block与函数的对比 :
声明 函数类型 : int ( * funcptr )(int);
声明Block类型 : int (^ blk)(int);
函数使用typedef : typedef int (^blk_t) (int);使用的时候就直接使用blk_t
Block使用typedef : typedef int (* funcptr) (int);赋值的时候是用函数的地址funcptr func = &addTen;
例子 blk_t blt = ^int (int a){//返回值一般不写,参数列表是要有()
return 4;
};
截取自动变量值 : Block截获所使用的自动变量的值,不使用的是不会截获的。即保存该自动变量的瞬时值,在执行Block的语法后,即使改写Block中使用的自动变量的值也不会影响Block执行时自动变量的值。
代码 :
(1)int a = 10;
blk_t block = ^ {
NSLog(@"%d",a);
};
a = 100;
block();//打印之后的结果是10而不是100
(2)Person * p = [[Person alloc]init];
p.name = @"张三";
blk_t block = ^ {
//获取的是地址,并不是对象的本身
NSLog(@"%@",p.name);
[p1 release];
};
p.name = @"李四";
[p release];
p = nil;
block();
} // [Person name]: message sent to deallocated instance 0x100300170
知识点和注意点 :
(1) 默认情况下,block不能修改外面的局部变量(基本数据类型),除非在前面加__Block
(2) Block语法表达式中使用的局部变量被作为成员变量追加到Block所在的结构体中
(3) Block可以作为函数的参数,调用Block之前一定要判断,Block可以为nil
(4) 使用Block的时候最好使用typedef
(5) 如果获取的是引用的话,是可以修改对象的属性的,不要加__Block也是可以修改的
(6) 在block中使用retain好像没有效果,但是使用release是可以的