如果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 結(jié)構(gòu)體
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修飾后,局部變量會被轉(zhuǎn)化一個對象,局部變量的值將會是這個對象一個成員變量,而截獲的是這個對象。
與沒有__block修飾區(qū)分開,沒有__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);
}