Objective-C的Block實(shí)質(zhì)與實(shí)現(xiàn)探究 part-4

Block中使用__block變量的情況

</br>

Block要修改值的第二種方法:使用__block說(shuō)明符艇搀,全稱(chēng)為__block存儲(chǔ)域類(lèi)說(shuō)明符刊殉。C語(yǔ)言中有以下存儲(chǔ)域類(lèi)說(shuō)明符:

  • typedef
  • extern
  • static
  • auto
  • register

__block說(shuō)明符類(lèi)似于staticautoregister說(shuō)明符炮车,它們用于指定將變量值設(shè)置到哪個(gè)存儲(chǔ)域中舵变。例如酣溃,auto表示作為自動(dòng)變量存儲(chǔ)在棧中,static表示作為靜態(tài)變量存儲(chǔ)在數(shù)據(jù)區(qū)中纪隙。以下是分析例子:

Objective-C

__block int val = 10;
void (^blk)(void) = ^{ val = 1; };

C++

struct __Block_byref_val_0 { 
    void *__isa;
    __Block_byref_val_0 *__forwarding;
    int __flags;
    int __size;
    int val;
};

struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0 *Desc;
    __Block_byref_val_0 *val;

    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val, int flags=0) : val(_val->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    __Block_byref_val_0 *val = __cself->val;
    
    (val->__forwarding->val) = 1;
}

static void __main_block_copy_0 (struct __main_block_impl_0 *dst, struct __main_block_impl_0 *src) {
    _Block_object_assign(&dst->val, src->val, BLOCK_FIELD_IS_BYREF);
}

static void __main_block_dispose_0(struct __main_block_impl_0 *src) {
    _Block_object_dispose(src->val, BLOCK_FIELD_IS_BYREF);
}

static struct __main_block_desc_0 {
    unsigned long reserved;
    unsigned long Block_size;
    void (*copy)(struct __main_block_impl_0 *, struct __main_block_impl_0 *);
    void (*dispose)(struct __main_block_impl_0 *);
}  __main_block_desc_0_DATA = {
    0,
    sizeof(struct __main_block_impl_0),
    __main_block_copy_0,
    __main_block_dispose_0
};

int main() {

    __Block_byref_val_0 val = {
        0,
        &val,
        0,
        sizeof(__Block_byref_val_0),
        10
    };

    blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);

    return 0;
}
Block數(shù)據(jù)結(jié)構(gòu)圖(6)

新增的部分以粉紅色顯示赊豌。

從圖中看到,__block變量被轉(zhuǎn)換為_Block_byref_val_0結(jié)構(gòu)體绵咱,Block的成員變量有一個(gè)指向該結(jié)構(gòu)體的指針碘饼。Block成員變量保留指針而不是一個(gè)結(jié)構(gòu)體的設(shè)計(jì),是為了能夠在多個(gè)Block使用__block變量悲伶。下面是說(shuō)明這個(gè)問(wèn)題的例子艾恼。

__block int val = 10;
void (^blk0)(void) = ^{ val = 0;};
void (^blk1)(void) = ^{ val = 1;};
__Block_byref_val_0 val = {
    0, 
    &val, 
    0,
    sizeof(__Block_byref_val_0),
    10
};

blk0 = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);

blk1 = &__main_block_impl_1(__main_block_func_1, &__main_block_desc_1_DATA, &val, 0x22000000);

兩個(gè)Block都使用了__Block_byref_val_0結(jié)構(gòu)體實(shí)例val的指針。這樣一來(lái)就可以從多個(gè)Block中使用同一個(gè)__block變量麸锉。當(dāng)然钠绍,反過(guò)來(lái)從一個(gè)Block中使用多個(gè)__block變量也沒(méi)有問(wèn)題。只要增加Block的結(jié)構(gòu)體成員變量與構(gòu)造函數(shù)的參數(shù)花沉,便可對(duì)應(yīng)使用多個(gè)__block變量柳爽。

Block數(shù)據(jù)結(jié)構(gòu)圖(6)中Desc新增的兩個(gè)函數(shù)指針,copy函數(shù)用于?復(fù)制Block碱屁,dispose函數(shù)用于廢棄Block磷脯。

《Objective-C高級(jí)編程 iOS與OS X多線程和內(nèi)存管理》表2-6

上例的int型__block變量轉(zhuǎn)換成結(jié)構(gòu)體之后,有一個(gè)void *__isa指針的成員變量娩脾,這說(shuō)明我們也可以把它看作實(shí)例赵誓。

《Objective-C高級(jí)編程 iOS與OS X多線程和內(nèi)存管理》表2-2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晦雨,隨后出現(xiàn)的幾起案子架曹,更是在濱河造成了極大的恐慌隘冲,老刑警劉巖闹瞧,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異展辞,居然都是意外死亡奥邮,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)罗珍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洽腺,“玉大人,你說(shuō)我怎么就攤上這事覆旱≌号螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵扣唱,是天一觀的道長(zhǎng)藕坯。 經(jīng)常有香客問(wèn)我团南,道長(zhǎng),這世上最難降的妖魔是什么炼彪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任吐根,我火速辦了婚禮,結(jié)果婚禮上辐马,老公的妹妹穿的比我還像新娘拷橘。我一直安慰自己,他們只是感情好喜爷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布冗疮。 她就那樣靜靜地躺著,像睡著了一般贞奋。 火紅的嫁衣襯著肌膚如雪赌厅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天轿塔,我揣著相機(jī)與錄音特愿,去河邊找鬼。 笑死勾缭,一個(gè)胖子當(dāng)著我的面吹牛揍障,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俩由,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼毒嫡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了幻梯?” 一聲冷哼從身側(cè)響起兜畸,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碘梢,沒(méi)想到半個(gè)月后咬摇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡煞躬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年肛鹏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恩沛。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡在扰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雷客,到底是詐尸還是另有隱情芒珠,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布搅裙,位于F島的核電站皱卓,受9級(jí)特大地震影響总放,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜好爬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一局雄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧存炮,春花似錦炬搭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至享完,卻和暖如春灼芭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背般又。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工彼绷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茴迁。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓寄悯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親堕义。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猜旬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

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