《Objective-C高級(jí)編程》Blocks 閱讀筆記系列
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item1(Blocks概要和模式)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item2(Block的實(shí)質(zhì))
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item3(截獲自動(dòng)變量值)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item4(__block說(shuō)明符)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item5(Block存儲(chǔ)域)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item6(__block變量存儲(chǔ)域)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item7(截獲對(duì)象)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item8(__block變量和對(duì)象)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item9(Block循環(huán)引用)
《Objective-C高級(jí)編程》Blocks 閱讀筆記 item10(copy/release實(shí)例方法)
2.3 Blocks的實(shí)現(xiàn)
2.3.9 copy/release
*** ARC無(wú)效時(shí),需要用copy實(shí)例方法手動(dòng)將Blocl從棧復(fù)制到堆遇绞,用release實(shí)例方法來(lái)釋放復(fù)制的Block亚亲。 ***
void (^blk_on_heap)(void) = [blk_on_stack copy];
[blk_on_heap release];
*** 只要Block有一次復(fù)制并配置在堆上娶聘,就可通過(guò)retain實(shí)例方法持有蹦误。***
[blk_on_heap retain];
*** 但是扔仓,對(duì)于配置在棧上的Block調(diào)用retain實(shí)例方法則不起任何作用芜赌。 ***
[blk_on_stack retain];
該源代碼中其爵,雖然對(duì)賦值給blk_on_stack的棧上的Block調(diào)用了retain實(shí)例方法冒冬,但實(shí)際上對(duì)此源代碼不起任何作用。因此摩渺,推薦使用copy實(shí)例方法來(lái)持有Block(不用retain實(shí)例方法)简烤。
由于Block是C語(yǔ)言的擴(kuò)展,所以在C語(yǔ)言中也可以使用Block語(yǔ)法摇幻。此時(shí)使用“Block_copy函數(shù)”和“Block_release函數(shù)”代替copy/release實(shí)例方法横侦。
void (^blk_on_heap)(void) = Block_copy(blk_on_stack);
Block_release(blk_on_heap);
*** ARC無(wú)效時(shí),__block說(shuō)明符被用來(lái)避免Block中的循環(huán)引用绰姻。***
這是由于當(dāng)Block從棧復(fù)制到堆時(shí)枉侧,若Block使用的變量為附有__block說(shuō)明符的id類型或?qū)ο箢愋偷淖詣?dòng)變量,不會(huì)被retain狂芋;若Block使用的變量為沒(méi)有__block說(shuō)明符的id類型或?qū)ο箢愋偷淖詣?dòng)變量榨馁,則被retain。
typedeft void (^blk_t)(void);
@interface MyObject : NSObject
{
blk_t blk_;
}
@end
@implementation MyObject
- (id)init
{
self = [super init];
blk_ = ^{NSLog(@"self = %@", self);};
return self;
}
- (void)dealloc
{
NSLog(@"dealloc");
}
@end
int main()
{
id o = [[MyObject alloc] init];
NSLog(@"%@", o);
return 0;
}
該源代碼無(wú)論ARC有效還是無(wú)效都會(huì)引起循環(huán)引用帜矾,Block持有self翼虫,self持有Block屑柔。
可使用__block變量來(lái)避免出現(xiàn)該問(wèn)題。
- (id)init
{
self = [super init];
__block id blockSelf = self;
blk_ = ^{NSLog(@"self = %@", blockSelf);};
return self;
}
這時(shí)珍剑,由于Block使用__block變量掸宛,所以不會(huì)被retain。
注意
- ARC有效時(shí)招拙,__block說(shuō)明符和__unsafe_unretained修飾符一起使用旁涤,來(lái)解決附有__unsafe_unretained修飾符的自動(dòng)變量不能retain的問(wèn)題。
- __block說(shuō)明符在ARC有效無(wú)效時(shí)的用途有很大的區(qū)別迫像,所以,在使用__block說(shuō)明符必須清楚源代碼是在ARC有效還是無(wú)效的情況下編譯瞳遍。