File tree Expand file tree Collapse file tree 1 file changed +40
-5
lines changed Expand file tree Collapse file tree 1 file changed +40
-5
lines changed Original file line number Diff line number Diff line change @@ -654,17 +654,52 @@ autoreleasepool 以一个队列数组的形式实现,主要通过下列三个函
654654检测代码中是否存在循环引用问题,可使用 Facebook 开源的一个检测工具 [***FBRetainCycleDetector***](https://github.com/facebook/FBRetainCycleDetector) 。
655655
656656###38. 在block内如何修改block外部变量?
657- 默认情况下,在block中访问的外部变量是复制过去的,即:**写操作不对原变量生效**。但是你可以加上`__block`来让其写操作生效,示例代码如下:
657+ 默认情况下,在block中访问的外部变量是复制过去的,即:**写操作不对原变量生效**。但是你可以加上 `__block` 来让其写操作生效,示例代码如下:
658658
659+
660+ ```Objective-C
659661 __block int a = 0;
660- void (^foo)(void) = ^{
662+ void (^foo)(void) = ^{
661663 a = 1;
662- }
663- f00 ();
664+ };
665+ foo ();
664666 //这里,a的值被修改为1
667+ ```
668+
669+
670+ 这是 [ 微博@唐巧_boy] ( http://weibo.com/tangqiaoboy ) 的《iOS开发进阶》中的第11.2.3章节中的描述。你同样可以在面试中这样回答,但你并没有答到“点子上”。真正的原因,并没有书这本书里写的这么“神奇”,而且这种说法也有点牵强。面试官肯定会追问“为什么写操作就生效了?”正真的原因是这样的:
671+
672+
673+ > 被 ` __block ` 关键字修饰的外部对象,被 block 内部被引用后,该对象的指针地址就会由栈区变成堆区的地址。栈区内容出了作用域就会被销毁,堆区内容则不会。
674+
675+ 我们可以打印下内存地址来进行验证:
665676
677+ ``` Objective-C
678+ __block int a = 0 ;
679+ NSLog (@" 定义前:%p " , &a); // 栈区
680+ void (^foo)(void) = ^{
681+ a = 1;
682+ NSLog(@"block内部:%p", &a); //堆区
683+ };
684+ NSLog(@"定义后:%p", &a); //堆区
685+ foo();
686+ ```
687+
688+ ```Objective-C
689+ 2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] 定义前:0x16fda86f8
690+ 2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] 定义后:0x155b22fc8
691+ 2016-05-17 02:03:33.559 LeanCloudChatKit-iOS[1505:713679] block内部: 0x155b22fc8
692+ ```
693+
694+ 他们三个的内存地址转成10进制就是
695+
696+ 1 . 定义后前:6171559672
697+ 2 . block内部:5732708296
698+ 3 . 定义后后:5732708296
699+
700+ 中间相差 418.5M 的空间,又因为iOS中栈区的内存只有1M,Mac也只有8M,显然a已经是在堆区了。
666701
667- 参考链接:[微博@唐巧_boy](http://weibo.com/tangqiaoboy)的著作《iOS开发进阶》中的第11.2.3章节
702+ 这也证实了我们的猜测:a 在定义前是栈区,但只要进入了 block 区域,就变成了堆区。这才是 ` __block ` 关键字的真正作用。
668703
669704###39 . 使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?
670705
You can’t perform that action at this time.
0 commit comments