《Objective-C高级编程》Blocks 阅读笔记系列
《Objective-C高级编程》Blocks 阅读笔记 item1(Blocks概要和模式)
《Objective-C高级编程》Blocks 阅读笔记 item2(Block的实质)
《Objective-C高级编程》Blocks 阅读笔记 item3(截获自动变量值)
《Objective-C高级编程》Blocks 阅读笔记 item4(__block说明符)
《Objective-C高级编程》Blocks 阅读笔记 item5(Block存储域)
《Objective-C高级编程》Blocks 阅读笔记 item6(__block变量存储域)
《Objective-C高级编程》Blocks 阅读笔记 item7(截获对象)
《Objective-C高级编程》Blocks 阅读笔记 item8(__block变量和对象)
《Objective-C高级编程》Blocks 阅读笔记 item9(Block循环引用)
《Objective-C高级编程》Blocks 阅读笔记 item10(copy/release实例方法)
2.3 Blocks的实现
2.3.5 __block变量存储域
从“Block存储域”一节可知,*** 使用__block变量的Block从栈复制到堆上时,__block变量也会受到影响。 ***
表 Block从栈复制到堆时对__block变量产生的影响
__block变量的配置存储域 | Block从栈复制到堆时的影响 |
---|---|
栈 | 从栈复制到堆并被Block持有 |
堆 | 被Block持有 |
*** 在一个Block中使用__block变量 ***
*** 在多个Block中使用__block变量 ***
*** Block的废弃和__block变量的释放 ***
遗留的问题
“Block存储域”一节中遗留的问题:
- 使用__block变量的结构体成员变量__forwarding的原因
*** 不管__block变量配置在栈上还是在堆上,都能够正确地访问该变量 ***
正如这句话所诉,通过Block的复制,__block变量也会从栈复制到堆上。此时可同时访问栈上的__block变量和堆上的__block变量。
__block int val = 0; // __block变量
void (^blk)(void) = [^{++val;} copy]; // Block
++val;
blk();
NSLog(@"%d", val);
利用copy方法复制使用了__block变量的Block语法。此时,Block和__block变量均从栈复制到堆。
*** 在Block语法表达式中,使用初始化后的__block变量 ***
^{++val;}
*** 在Block语法表达式之后,使用与Block无关的__block变量 ***
++val;
然而,以上两种源代码都可以转换为:
++(val.__forwaring->val);
在变化Block语法的函数中,该变量val为 *** 复制到堆上的__block变量的结构体实例 ,而使用与Block无关的变量val,为 复制前栈上的__block变量的结构体实例 ***。
但是,栈上的__block变量的结构体实例(即变量val)在__block变量从栈复制到堆上时,会将成员变量__forwarding的值替换为复制目标堆上的__block变量的结构体实例的地址。