前提:Objective-C规定,在block中不能修改外部变量的值,若想修改则需在变量前边加__block关键字修饰
理解:
- (void)_testBlock{
int a = 0;
NSLog(@"block before:%p",&a);
void (^func)(void) = ^{
NSLog(@"block in:%p",&a);
};
NSLog(@"block after:%p",&a);
func();
}
- block中不能修改外部变量的值?
block中外部变量的值是被拷贝过去的,相当于值引用,并非变量原地址;
由上方代码的输出结果可见:
2018-03-15 16:20:44.982696+0800 iOSLearnigDemo[18642:1907706] block before:0x7ffeef0df60c
2018-03-15 16:20:44.983465+0800 iOSLearnigDemo[18642:1907706] block after:0x7ffeef0df60c
2018-03-15 16:20:44.983591+0800 iOSLearnigDemo[18642:1907706] block in:0x600000446e00
block before和block after的地址一致,和block内的地址不同,说明变量的地址没变,相当于值引用
- 加__block关键字之后,可以修改了?
前边加入__block关键字修饰之后,变量地址会被拷贝到堆区
2018-03-15 16:38:32.129721+0800 iOSLearnigDemo[18779:1930598] block before:0x7ffee4897608
2018-03-15 16:38:32.129958+0800 iOSLearnigDemo[18779:1930598] block after:0x600000238d78
2018-03-15 16:38:32.130968+0800 iOSLearnigDemo[18779:1930598] block in:0x600000238d78
block in和block after的地址是一致的,说明变量的地址变化,相当于地址引用
我们可以更进一步,利用clang 生成runtime编译后的源文件,加深理解
2. 加深理解
方式:利用clang -rewrite-objc 生成编译后的代码,用源码解读
编译完成的代码如下图所示:
编译完成的代码对比,左侧为加了__block关键字代码
- 未加__block关键字时,编译后的核心代码如下:
void test_block(){
int a = 0;
printf("block before:%p",&a);
void (*func)(void) = ((void (*)())&__test_block_block_impl_0((void *)__test_block_block_func_0, &__test_block_block_desc_0_DATA, a)); //注意此处传递给__test_block_block_impl_0函数的最后一个参数为a,所以是值传递
printf("block after:%p",&a);
((void (*)(__block_impl *))((__block_impl *)func)->FuncPtr)((__block_impl *)func);
}
- 加入__block关键字之后,编译的核心代码如下:
void test_block(){
__attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 0};
printf("block before:%p",&(a.__forwarding->a));
void (*func)(void) = ((void (*)())&__test_block_block_impl_0((void *)__test_block_block_func_0, &__test_block_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
printf("block after:%p",&(a.__forwarding->a));
((void (*)(__block_impl *))((__block_impl *)func)->FuncPtr)((__block_impl *)func);
}
通过查看生成的_test_block_block_impl_0函数中a参数基本就能明白
具体细节,我有空再写~
网友评论