Block
用一张图来解释:
block
是Objective-c
语言对闭包的实现:
闭包是一个函数(或指向函数的指针),再加上该函数执行的外部的上下文变量(有时候也称作自由变量)。
#Block中变量的复制与修改.
block之外的变量引用,block默认是将其复制到其数据结构中来实现的。入下图:(注意是定义block的时候复制的)
通过block
进行闭包的变量是const
的。也就是说不能在block中直接修改这些变量。 如果修改,编译器会报错。如果确实需要在block中处理变量,用__block关键字声明变量.
对于用__block
修饰的外部变量引用,block是复制其引用地址来实现访问的,如下图:
Block的类型
block有几种不同的类型:
- NSConcreteGlobalBlock:全局静态Block,不访问任何外部变量,不会涉及到任何拷贝.
- NSConcreteStackBlock:有访问到外部变量的Block,该保存在栈中,当函数返回时被销毁。
- NSConcreteMallocBlock:保存在堆中的Block,引用计数为0的时候被销毁.该类型的Block是由NSConcreteStackBlock 复制到堆中形成的。
NSConcreteGlobalBlock类型的Block
例子:
void(^p)() = ^(){
printf("Hello, World!\n");
}
NSConcreteGlobalBlock
类型的Block
要么是空的Block
,要么是不访问任何外部变量的block
。它既不在栈中,也不在堆中,我理解为它可能在内存的全局区。
NSConcreteStackBlock 类型的Block
例子:
int a;
void(^p)() = ^(){
printf("int a = %d\n",a);
}
_NSConcreteStackBlock
类型的block有闭包行为,也就是有访问外部变量,并且该block只且只有有一次执行,因为栈中的空间是可重复使用的,所以当栈中的block执行一次之后就被清除出栈了,所以无法多次使用。
NSConcreteMallocBlock类型的Block
例子:
void exampleB_addBlockToArray(NSMutableArray *array) {
char b = 'B';
//将block 放入到数组中
[array addObject:^{
printf("%c\n", b);
}];
}
void exampleB() {
NSMutableArray *array = [NSMutableArray array];
exampleB_addBlockToArray(array);
//复制行为导致block 是从栈中复制到堆中。
void (^block)() = [array objectAtIndex:0];
block();
}
_NSConcreteMallocBlock
类型的block
有闭包行为,并且该block需要被多次执行。当需要多次执行时,就会把该block从栈中复制到堆中,供以多次执行。
#Block的数据结构定义
Block_layout
就是对block
结构体的定义:
对应结构体如下:
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
isa指针:指向表明该block类型的类。所有对象都有该指针,用于实现对象相关的功能。
flags:按bit位表示一些block的附加信息,比如判断block类型、判断block引用计数、判断block是否需要执行辅助函数等。
reserved:保留变量,我的理解是表示block内部的变量数。
invoke:函数指针,指向具体的block实现的函数调用地址。
descriptor: block的附加描述信息,比如保留变量数、block的大小、进行copy或dispose的辅助函数指针。
variables:因为block有闭包性,所以可以访问block外部的局部变量。这些variables就是复制到结构体中的外部局部变量或变量的地址。
#ARC下使用Block的坑总结
参考文章:
6: http://www.cocoachina.com/ios/20130711/65755]: http://www.cocoachina.com/ios/20150109/10891.html