关于 block 会不会被自动 copy 的实验和猜想
许风颖
8年前
<p>今天群里不知怎么说起了 block 在栈上还是在堆上的问题。好像之前在哪里看到过,现在 block 的属性已经不用写 copy 关键字,就会自动 copy。于是做了几个实验,想看看什么情况下会自动 copy,什么情况下不会~</p> <h2>实验</h2> <p>代码如下:</p> <p>TestClass.h</p> <pre> <code class="language-objectivec">typedef void(^SimpleBlock)(); @interface TestClass : NSObject @property (nonatomic, copy) SimpleBlockcopyProperty; @property (nonatomic, strong) SimpleBlockstrongProperty; @property (nonatomic, weak) SimpleBlockweakProperty; @property (nonatomic, assign) SimpleBlockassignProperty; @end </code></pre> <p>main</p> <pre> <code class="language-objectivec">#import "TestClass.h" SimpleBlocksomeFunction(SimpleBlockblock) { NSLog(@"block as param : %@", block); return block; } int main(int argc, const char * argv[]) { @autoreleasepool { __blockint a = 1; NSLog(@"orginal block : %@", ^{ a = 2; }); // as a variable SimpleBlockblock = ^{ a = 2; }; NSLog(@"block as variable : %@", block); __weakSimpleBlockweakBlock = ^{ a = 2; }; NSLog(@"block as a weak variable : %@", weakBlock); // as properties TestClass* testClass = [TestClassnew]; testClass.weakProperty = ^{ a = 2; }; testClass.assignProperty = ^{ a = 2; }; testClass.copyProperty = ^{ a = 2; }; testClass.strongProperty = ^{ a = 2; }; NSLog(@"copy property : %@", testClass.copyProperty); NSLog(@"strong property : %@", testClass.strongProperty); NSLog(@"weak property : %@", testClass.weakProperty); NSLog(@"assign property : %@", testClass.assignProperty); NSLog(@"block as return value : %@", someFunction(^{ a = 2; })); } return 0; } </code></pre> <p>实验结果:</p> <pre> <code class="language-objectivec">2017-02-06 17:43:36.207212 test2[27378:1079138] orginalblock : 2017-02-06 17:43:36.207436 test2[27378:1079138] blockas variable : 2017-02-06 17:43:36.207457 test2[27378:1079138] blockas a weakvariable : 2017-02-06 17:43:36.207492 test2[27378:1079138] copyproperty : 2017-02-06 17:43:36.207517 test2[27378:1079138] strongproperty : 2017-02-06 17:43:36.207563 test2[27378:1079138] weakproperty : 2017-02-06 17:43:36.207581 test2[27378:1079138] assignproperty : 2017-02-06 17:43:36.207611 test2[27378:1079138] blockas param : 2017-02-06 17:43:36.207769 test2[27378:1079138] blockas return value : </code></pre> <h2>分析</h2> <ul> <li>作为变量: <ul> <li>一个 block 刚声明的时候是在栈上</li> <li>赋值给一个普通变量之后就会被 copy 到堆上</li> <li>赋值给一个 weak 变量不会被 copy</li> </ul> </li> <li>作为属性: <ul> <li>用 strong 和 copy 修饰的属性会被 copy</li> <li>用 weak 和 assign 修饰的属性不会被 copy</li> </ul> </li> <li>函数传参: <ul> <li>作为参数传入函数不会被 copy</li> <li>作为函数的返回值会被 copy</li> </ul> </li> </ul> <h2>猜测</h2> <p>看着以上结论,感觉可以做出一个猜测:就是 block 被 retain 的时候就会自动被 copy,包括 autoRelease~ 这样就能解释为啥函数的参数不会被 copy,返回值就会被 copy。是不是很有道理呢 =w=</p> <p> </p> <p> </p> <p>来自:http://ios.jobbole.com/92865/</p> <p> </p>