关于 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>