先上结论,block作为参数使用时
1、mrc下使用block要手动拷贝到堆上
2、arc下不用,会自动拷贝到堆上
举一个写异步线程处理的代码时出现一个crash的例子,截图如下
可以看到,task是个block,现在已经为null了,调用发生了crash
可以看下整个调用的过程:
1、调用一个接口,传入block
2、接口实现里将block放到了异步线程去处理,然后返回
3、接着就是如上面那个doBlock的那个图了,执行时task变为了null
究其原因,是因为我使用的是mrc来编译,传入block(即task)到asyncWork时,这个task在栈上,如下图,是__NSStackBlock__类型的block
然后调用performSelector将其传入异步线程去处理,由于是异步线程,这时候会立即返回,再返回到最初调用asyncWork的地方执行结束后,栈被收回了,所以task成了null了,自然发生了crash。
解决方案:
1、 如果一定是mrc,使用copy将block拷贝到堆上,这样有着引用,自然不会被回收,结果如下
threadTask tmptask = [[task copy] autorelease];
2、改为arc,这样调用时候会自动拷贝到堆上
调用处还是栈block
传入方法里便是堆block了
网友评论