block的循环引用问题2(block为什么用copy修饰)及处理循环引用

block的循环引用问题2(block为什么用copy修饰)及处理循环引用

Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的

另外需要注意线程安全问题,在调用block时另一个线程有没有可能去修改block如果有, 那就用nomatomic

比如这样一个Block类型:
typedef void (^MyBlockType)(int);

属性声明:
@property (copy) MyBlockType myBlock;

这里ARC和非ARC声明都是一样的,当然注意在非ARC下要release Block。

但是,有了atomic来保证基本的原子性还是没有达到线程安全的,接着在调用时需要把Block先赋值给本地变量,以防止Block突然改变。因为如果不这样的话,即便是先判断了Block属性不为空,在调用之前,一旦另一个线程把Block属性设空了,程序就会crash,如下代码:
if (self.myBlock)
{
//此时,走到这里,self.myBlock可能被另一个线程改为空,造成crash
//注意:atomic只会确保myBlock的原子性,这种操作本身还是非线程安全的
self.myBlock(123);
}

所以正确的代码是(ARC):
MyBlockType block = self.myBlock;
//block现在是本地不可变的
if (block)
{
block(123);
}

在非ARC下则需要手动retain一下,否则如果属性被置空,本地变量就成了野指针了,如下代码:
//非ARC
MyBlockType block = [self.myBlock retain];
if (block)
{
block(123);
}
[block release];

参考百度知道:iOS block为什么用copy修饰

处理方法:

block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增加

(需要禁止block对self进行强引用或者强制增加引用计数)

1.ARC:  __weaktypeof(self) weakSelf=self; 其实 __weak someClass *weakSelf = self也是OK的!

2.MRC:解决方式与上述基本一致,只不过将__weak关键字换成__block即可!

参考:http://blog.csdn.net/qq_26544491/article/details/46341993

   http://www.cnblogs.com/kesalin/archive/2013/04/30/ios_block.html