Block
使用^来声明一个block变量
void (^printBlock)(NSString *x);
printBlock =^(NSString *str){
NSLog(@"print:%@",str);
};
返回值 ^block名 形参 {块内容}
概述
- 在很多情况下,并不需要将block声明一个变量,在需要使用block的地方直接用内嵌的方式将block的内容写出来
- 一般来说block只能读取在同一个作用于的变量而没有办法修改在block外定义的任何变量,此时若我们想这些变量能在block中被修改,就必须使用
__block
修饰词。如下,有修饰词的变量可写,没有__block修饰的变量只读-
__block
不能修饰长度为不定值的变量
-
__block int NBNum = 1;
int notNBNum = 0;
void (^doSomeThing)(int n);
doSomeThing = ^(int n){
NBNum++;
NSLog(@"%d",NBNum);
NSLog(@"%d",notNBNum)
};
功能
Block是一种具有匿名功能的内嵌函数,
-
它的特性如下:
- 形参
- 有返回值
- lexical scope(作用域)
它的使用时机:表示,简化一段代码,特别适合用于封装一些小型的task或者作为一个工作完成的callback
-
它的优点(相对于
delegate
和callback
):- 可以直接在block中直接写入等下要执行的代码,直接将代码变成函数的参数传入函数中,这是block最常使用的地方
- 可以存储局部变量,传统的callback读写局部变量需要把数据封装成一个结构体,而block可以直接存取
-
引用计数
- 如果在blcok中引用了OC对象,那么引用计数+1;__block对引用计数无影响
-
使用注意
- 避免在if for循环等局部定义域内定义block并在其外面引用
Block的本质
当你定义完block之后,其实是创建了一个函数,在创建结构体的时候把函数的指针一起传给了block,所以之后可以拿出来调用
__block修饰的变量传入Blcok是地址传递,普通变量传入block是值传递
Block的三种状态:
_NSConcreteGlobalBlock
全局静态;_NSConcreteStackBlock
栈保存,函数作用域外销毁;_NSConcreteMallocBlock
堆保存,retain == 0销毁