《Objective-C高級(jí)編程》Blocks 閱讀筆記 item8(__block變量和對(duì)象)

《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說明符)
《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.7 __block變量和對(duì)象

*** 附加__strong修飾符的對(duì)象類型__block變量和自動(dòng)變量***
__block說明符可指定“任何類型”的自動(dòng)變量。
下面指定用于賦值Objective-C對(duì)象的id類型自動(dòng)變量:

__block id obj = [[NSObject alloc] init];

ARC有效時(shí),id類型以及對(duì)象類型變量默認(rèn)附加__strong修飾符。
所以,該代碼等同于:

__block id __strong obj = [[NSObject alloc] init];

經(jīng)clang轉(zhuǎn)換:

/* __block變量的結(jié)構(gòu)體部分 */

// 結(jié)構(gòu)體 __Block_byref_obj_0
struct __Block_byref_obj_0 {
    void *__isa;
    __Block_byref_obj_0 *__forwarding;
    int __flags;
    int __size;
    void (*__Block_byref_id_object_copy)(void*, void*);
    void (*__Block_byref_id_object_dispose_)(void*);
    __strong id obj; // __block變量被追加為成員變量
};

// 靜態(tài)函數(shù) __Block_byref_id_object_copy_131
static void __Block_byref_id_object_copy_131(void *dst, void *src){
    _Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
}

// 靜態(tài)函數(shù) __Block_byref_id_object_dispose_131
static void __Block_byref_id_object_dispose_131(void *src){
    _Block_object_dispose(*(void * *) ((char*)src + 40), 131);
}
/* __block變量聲明部分 */

__Block_byref_obj_0 obj = {
    0,
    &obj,
    0x20000000,
    sizeof(__Block_byref_obj_0),
    __Block_byref_id_object_copy_131,
    __Block_byref_id_object_dispose_131,
    [[NSObject alloc] init]
};

Block中使用“附有__strong修飾符的id類型或?qū)ο箢愋妥詣?dòng)變量”的情況下,當(dāng)Block從棧復(fù)制到堆時(shí),使用_Block_object_copy函數(shù),持有Block截獲的對(duì)象。當(dāng)堆上的Block被廢棄時(shí),使用_Block_object_dispose函數(shù),釋放Block截獲的對(duì)象

__block變量“附有__strong修飾符的id類型或?qū)ο箢愋妥詣?dòng)變量”的情形下會(huì)發(fā)生同樣的過程。當(dāng)__block變量從棧復(fù)制到堆時(shí),使用_Block_object_copy函數(shù),持有賦值給__block變量的對(duì)象。當(dāng)堆上的__block變量被廢棄時(shí),使用_Block_object_dispose函數(shù),釋放賦值給__block變量的對(duì)象

由此可知,即時(shí)對(duì)象賦值給“復(fù)制到堆上的附有__strong修飾符的對(duì)象類型__block變量”中,只要__block變量在堆上繼續(xù)存在,那么該對(duì)象就會(huì)繼續(xù)處于被持有的狀態(tài)。這與在Block對(duì)象賦值給“附有__strong修飾符的對(duì)象類型自動(dòng)變量”相同。

*** 附有__weak修飾符的id類型自動(dòng)變量 ***
Block中使用附有__weak修飾符的id類型自動(dòng)變量

blk_t blk;

{
    id array = [[NSMutableArray alloc] init];
    id __weak weakArray = array;
    
    blk = [^(id obj){
        
        [weakArray addObject:obj];
        
        NSLog(@"weakArray count = %ld", [weakArray count]);
    } copy];
}

blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);

執(zhí)行結(jié)果:

weakArray count = 0
weakArray count = 0
weakArray count = 0

該段代碼能夠正常運(yùn)行。這是因?yàn)樵谧兞孔饔糜蚪Y(jié)束時(shí),附有__strong修飾符的自動(dòng)變量array所持有的NSMutableArray類對(duì)象會(huì)被釋放被廢棄,而附有__weak修飾符的自動(dòng)變量weakArray由于對(duì)NSMutableArray類對(duì)象持有弱引用,此時(shí)nil賦值在自動(dòng)變量weakArray上。

*** 附有__weak修飾符的__block變量 ***

blk_t blk;

{
    id array = [[NSMutableArray alloc] init];
    __block id __weak blockWeakArray = array;
    
    blk = [^(id obj){
        
        [blockWeakArray addObject:obj];
        
        NSLog(@"blockWeakArray count = %ld", [blockWeakArray count]);
    } copy];
}

blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);

執(zhí)行結(jié)果:

blockWeakArray count = 0
blockWeakArray count = 0
blockWeakArray count = 0

這段代碼也能正常運(yùn)行。這是因?yàn)榧磿r(shí)附加了__block說明符,在變量作用域結(jié)束時(shí),附有__strong修飾符的自動(dòng)變量array所持有的NSMutableArray類對(duì)象會(huì)被釋放被廢棄,而附有__weak修飾符的自動(dòng)變量blockWeakArray由于對(duì)NSMutableArray類對(duì)象持有弱引用,此時(shí)nil賦值在自動(dòng)變量blockWeakArray上。

注意

  • 由于附有__unsafe_unretained修飾符的變量只不過與指針相同,所以不管在Block中使用還是附加到__block變量中,也不會(huì)像__strong修飾符或__weak修飾符那樣進(jìn)行處理。在使用附有__unsafe_unretained修飾符的變量時(shí),注意不要通過懸掛指針訪問已被廢棄的對(duì)象,否則程序可能會(huì)崩潰!
  • 沒有設(shè)定__autoreleasing修飾符與Block同時(shí)使用。
  • __autoreleasing修飾符與__block說明符同時(shí)使用會(huì)產(chǎn)生編譯錯(cuò)誤。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,706評(píng)論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,203評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,451評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,677評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,857評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,407評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,643評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容