栈块
void (^block)();
if(){
block = ^(){
NSLog(@"block a");
}
}else{
block = ^{
NSLog(@"block b");
}
}
定义在if及else语句中的两个块都分配在栈内存中,编译器会给每个块分配好栈内存,然而等离开相应范围之后,编译器有可能把分配给块的内存复写掉,于是两个块只能保证在对应if和else语句范围之内有效,这样的程序有可能崩溃,
为解决这个问题,可以给块对象发送copy消息,这样把块从栈区复制到堆区,就可以在定义它的范围之外使用了,一旦复制到堆区了,快块就变成了带有引用计数器的对象了,,后续的复制操作都不会真的执行复制,只是在递增块对象的引用计数
全局块
全局块不会捕捉任何状态(比如外围的变量等),运行时也无需有状态参与进来,块所使用的整个内存区域,在编译期已经完全确定,因此,全局块可以申明在全局内存中,而不需要在每次用到的时候在栈中创建。另外全局块的拷贝操作是个空操作,因为全局块绝不可能为系统所回收,这种块相当于单例。
由于运行该块所需的全部信息都能在编译期确定,所以可能把他当做全局块
以typedef重新定义块类型,可另块变量用起来更加简单
定义新类型时应遵从现有的命名习惯,不要使其名称和别的类型相冲突
不妨为同一个块签名定义多个类型别名,如果要重构的代码使用了块类型的某个别名,那么只需要修改相应typedef的块签名即可,无需改动其他的typedef。
在创建对象时,可以使用内联的handler块将相关业务逻辑一并声明
在有多个实例需要监控时,如果采用委托模式,那么经常需要根据传入的对象来切换,而若改用handle块来实现,则可直接将块与相关对象放在一起。
设计api时,如果用到handler块,那么可以增加一个参数使调用者可通过此参数来决定应该把块安排在哪个队列上执行。
如果块所捕获的对象直接或间接的保留了块本身,那么就得当心循环引用
一定要找个适当时机解除保留环,而不能吧责任推给API调用者。