理解block(块)
block的结构
block结构图return_type (^block_name)(paratemters)
block的基本用法
int additional = 5;
int (^addBlock)(int a, int b) = ^(int a, int b){
return a + b+ addition;
}
默认情况下,为block所捕获的变量,是不可以在块里修改的(需要加__block)
NSArray *array = @[@0, @1, @2, @3, @4, @5];
__block int count = 0;
[array enumerateObjectsUsingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) {
if ([number compare:@2] == NSOrderedAscending) {
count ++;
}
}];
// count = 2;
块总能修改实例变量,所以在声明时无需加__block
在定义blcok的时候,所占内存分配的栈中的,这就是说,块只在定义他的那个范围内有效
一下代码就很危险
void (^block)();
if (count == 2) {
block = ^{
NSLog(@"Block A");
};
}else{
block = ^{
NSLog(@"Block B");
}
block();
首先栈内存是分配是有编译器分配和释放的,以上代码中if和else中的block被分配到栈内存中(这两个块只能保证在对应的if或else语句范围内有效),如果编译器把分配给block的内存给覆写掉,那么程序就会崩溃。
注意:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来讲,释放工作有程序员控制,容易产生memory Leak。
为解决以上问题,我们可以给block对象发送copy消息,把block从栈复制到堆上。
void (^block)();
if (count == 2) {
[block = ^{
NSLog(@"Block A");
} copy];
}else{
[block =^{
NSLog(@"Block B");
} copy];
}
block();
全局块
可以把块定义为全局变量,在文件级别上使用。全局块可以声明到全局内存中,而不需要在每次用到得时候于栈中创建。另外全局块的copy是个空操作,因为全局块绝不可能为系统所回收。
block一般有三种,NSConcreteGlobal, NSConcreteStack, NSConcreteMalloc。
block是可以访问block外部的变量的。
NSConcreteGlobal: 就像一个全局函数一样,从头到尾待在那,始终是可用的。当Block中没有引用外部变量时,block为global类型的。
NSConcreteStack: 保存在栈中的block,block执行完后内存会被释放掉。当block引用了外部变量时,block为stack类型的。
NSConcreteMallock: 保存在堆中的block,block为引用记数为0时,内存会被释放掉。当block执行copy时,block会从栈中复制到堆中。
以上都针对非ARC环境而言,如果在ARC环境下,引用外部变量的block会自动保存在堆中,无需copy。
待续。。。
block的理解http://answerhuang.duapp.com/index.php/2013/09/07/objective-c-blocks-syntax/#carousel-generic-38