1.block属性的声明
block属性的声明,需要copy修饰符,因为只有copy后的block才会在堆中,栈中的block的生命周期是和栈绑定的
2.block线程安全
在声明block属性时需要确认“在调用block时另一个线程有没有可能去修改block?”确定不会有,block声明可以用nonatomic。不确定(通常是不确定),需要 声明block属性为atomic,先保证变量的原子性。
比如这样一个block类型
typedef void (^MyBlockType)(int);
属性声明:@property(copy) MyBlockType myBlock;
但是,有atomic来保证基本的原子属性还是没有达到线程安全,接着在调用时需要把block先赋值给本地变量,以防止block突然改变。因为如果不这样的话,即便先判断了block属性不为空,在调用之前,一旦另一个线程把block属性设空了,程序就会crash
正确的代码是(ARC):
MyBlockType block = self.myBlock;//block现在是本地不可变
if(block){
block(123);
}
非ARC下需要手动retain一下,否则属性被置空,本地变量就成了野指针
MyBlockType block = [self.myBlock retain];
if(block){
block(123);
}
[block release];
3.循环引用
ARC下,由于__block抓取的变量一样会被block retain,所以必须用弱引用才可以解决循环引用问题,iOS5之后用__weak。
__weak typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt) {
[weakSelf anotherFunc];
};
非ARC,无法使用弱引用,用__block来修饰变量,它不会被block所retain的
__block typedef(self) blockSelf = self;
self.myBlock = ^(int paramInt) {
[blockSelf anotherFunc];
};
网友评论