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];
};