如果block需要捕获某个变量后进行赋值,这个变量在声明时需要使用 __block修饰。
void testBlock2() {
__block int num = 3;
void(^block)(int) = ^(int i){
num = 4;
NSLog(@"i * num = %d", num * i);
};
num = 5;
block(2);
}
clang -rewrite-objc main.m,查看main.cpp文件
void testBlock2() {
__attribute__((__blocks__(byref))) __Block_byref_num_0 num =
{(void*)0,(__Block_byref_num_0 *)&num, 0, sizeof(__Block_byref_num_0), 3};
void(*block)(int) = ((void (*)(int))&__testBlock2_block_impl_0((void *)__testBlock2_block_func_0,
&__testBlock2_block_desc_0_DATA, (__Block_byref_num_0 *)&num, 570425344));
(num.__forwarding->num) = 5;
((void (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 2);
}
__block修饰的局部变量基本类型变成了 __Block_byref_num_0 结构体
struct __Block_byref_num_0 {
void *__isa;
__Block_byref_num_0 *__forwarding;
int __flags;
int __size;
int num;
};
struct __testBlock2_block_impl_0 {
struct __block_impl impl;
struct __testBlock2_block_desc_0* Desc;
__Block_byref_num_0 *num; // by ref
__testBlock2_block_impl_0(void *fp, struct __testBlock2_block_desc_0 *desc,
__Block_byref_num_0 *_num, int flags=0) : num(_num->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
此时 _num->__forwarding 指向 __Block_byref_num_0 *num。
(num.__forwarding->num) = 5 这是再给num对象的num属性赋值。
__block修饰后,局部变量会被转化一个对象,局部变量的值将会是这个对象一个成员变量,而截获的是这个对象。
与没有__block修饰区分开,没有__block修饰时,是截获的值。
void testBlock2() {
__block int num = 3;
void(^block)(int) = ^(int i){
NSLog(@"i * num = %d", num * i);
};
num = 5;
block(2); // i * num = 10
}
void testBlock3() {
int num = 3;
void(^block)(int) = ^(int i){
NSLog(@"i * num = %d", num * i);
};
num = 5;
block(2); // i * num = 6
}
如果截获的变量,不赋值,仅仅是使用,不需要使用__block
void testBlock4() {
//不需要__block修饰,没有对array赋值,而仅仅是使用。
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
void(^block)(int) = ^(int i){
[array addObject:@(i)];
};
block(2);
}