OC中的Block(三)

block的類(lèi)型

block有3種類(lèi)型,可以通過(guò)調(diào)用class方法或者isa指針查看具體類(lèi)型辰妙,最終都是繼承自NSBlock類(lèi)型

  • __NSGlobalBlock__ (_NSConcreteGlobalBlock )
  • __NSStackBlock__ (_NSConcreteStackBlock )
  • __NSMallocBlock__ (_NSConcreteMallocBlock )
應(yīng)用程序內(nèi)存分配
程序區(qū)域 .text區(qū)
數(shù)據(jù)區(qū)域 .data區(qū)
堆區(qū)
棧區(qū)
不同類(lèi)型block的存放區(qū)域

生成不同類(lèi)型的block

block類(lèi)型 環(huán)境
NSGlobalBlock(數(shù)據(jù)區(qū)) 沒(méi)有訪問(wèn)auto變量
NSStackBlock(棧區(qū)) 訪問(wèn)了auto變量
NSMallocBlock(堆區(qū)) NSStackBlock調(diào)用了copy

每一種類(lèi)型的block調(diào)用copy后的結(jié)果如下所示:

block類(lèi)型 副本源的配置存儲(chǔ)域 復(fù)制效果
NSGlobalBlock(數(shù)據(jù)區(qū)) 棧區(qū) 從棧復(fù)制到堆區(qū)
NSStackBlock(棧區(qū)) 程序的數(shù)據(jù)區(qū) 什么也不做
NSMallocBlock(堆區(qū)) 堆區(qū) 引用計(jì)數(shù)增加

block的copy

在ARC環(huán)境下压状,編譯器會(huì)根據(jù)情況自動(dòng)將棧上的block復(fù)制到堆上仆抵,比如以下情況

  • block作為函數(shù)返回值時(shí)
  • 將block賦值給__strong指針時(shí)
  • block作為Cocoa API中方法名含有usingBlock的方法參數(shù)時(shí)
  • block作為GCD API的方法參數(shù)時(shí)

MRC下block屬性的建議寫(xiě)法

@property (copy, nonatomic) void (^block)(void);`

ARC下block屬性的建議寫(xiě)法

@property (strong, nonatomic) void (^block)(void);
@property (copy, nonatomic) void (^block)(void);

對(duì)象類(lèi)型的auto變量

當(dāng)block內(nèi)部訪問(wèn)了對(duì)象類(lèi)型的auto變量時(shí)

  • 如果block是在棧上,將不會(huì)對(duì)auto變量產(chǎn)生強(qiáng)引用

  • 如果block被拷貝到堆上

  1. 如果block被拷貝到堆上
  2. copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
  3. _Block_object_assign函數(shù)會(huì)根據(jù)auto變量的修飾符(__strong种冬、__weak镣丑、__unsafe_unretained)做出相應(yīng)的操作,形成強(qiáng)引用(retain)或者弱引用
函數(shù) 點(diǎn)用時(shí)機(jī)
__main_block_copy_0 棧上的block復(fù)制到堆時(shí)
__main_block_dispose_0 堆上的block被廢棄時(shí)
//block被拷貝到堆上時(shí)調(diào)用
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {

//會(huì)根據(jù)auto變量的修飾符(__strong碌廓、__weak、__unsafe_unretained)做出相應(yīng)的操作剩盒,形成強(qiáng)引用(retain)或者弱引用
_Block_object_assign((void*)&dst->obj,
                         (void*)src->obj,
                         8/*BLOCK_FIELD_IS_BYREF*/);
}

//block從堆上移除時(shí)調(diào)用
static void __main_block_dispose_0(struct __main_block_impl_0*src) {
//會(huì)自動(dòng)釋放引用的auto變量(release)
_Block_object_dispose((void*)src->obj,
                          8/*BLOCK_FIELD_IS_BYREF*/);
}

__weak修飾符

__weak修飾符可以是block生成的結(jié)構(gòu)體中捕獲的變量為_(kāi)_weak變量..則可以對(duì)變量進(jìn)行弱引用谷婆,解決循環(huán)引用問(wèn)題

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  //捕獲__weak變量
  NSString __weak *name;
  .
  .
  .
};

在使用clang轉(zhuǎn)換OC為C++代碼時(shí),可能會(huì)遇到以下問(wèn)題

cannot create __weak reference in file using manual reference

解決方案:支持ARC辽聊、指定運(yùn)行時(shí)系統(tǒng)版本纪挎,比如

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m

__block修飾符

__block可以用于解決block內(nèi)部無(wú)法修改auto變量值的問(wèn)題.但是__block不能修飾全局變量、靜態(tài)變量(static)

編譯器會(huì)將__block變量包裝成一個(gè)對(duì)象

__block int age = 13;
^{
    NSLog(@"%d", age);
}();

會(huì)生成一下C++代碼:

struct __main_block_impl_1 {
  struct __block_impl impl;
  struct __main_block_desc_1* Desc;
  __Block_byref_age_2 *age; // by ref
  __main_block_impl_1(void *fp, struct __main_block_desc_1 *desc, __Block_byref_age_2 *_age, int flags=0) : age(_age->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
struct __Block_byref_age_2 {
  void *__isa;
__Block_byref_age_2 *__forwarding;
 int __flags;
 int __size;
 int age;
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跟匆,一起剝皮案震驚了整個(gè)濱河市异袄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玛臂,老刑警劉巖烤蜕,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異迹冤,居然都是意外死亡讽营,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)泡徙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橱鹏,“玉大人,你說(shuō)我怎么就攤上這事±蚶迹” “怎么了挑围?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)糖荒。 經(jīng)常有香客問(wèn)我杉辙,道長(zhǎng),這世上最難降的妖魔是什么寂嘉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任奏瞬,我火速辦了婚禮,結(jié)果婚禮上泉孩,老公的妹妹穿的比我還像新娘硼端。我一直安慰自己,他們只是感情好寓搬,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布珍昨。 她就那樣靜靜地躺著,像睡著了一般句喷。 火紅的嫁衣襯著肌膚如雪镣典。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天唾琼,我揣著相機(jī)與錄音兄春,去河邊找鬼。 笑死锡溯,一個(gè)胖子當(dāng)著我的面吹牛赶舆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祭饭,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芜茵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了倡蝙?” 一聲冷哼從身側(cè)響起九串,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寺鸥,沒(méi)想到半個(gè)月后猪钮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胆建,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年躬贡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眼坏。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拂玻,死狀恐怖酸些,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檐蚜,我是刑警寧澤魄懂,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站闯第,受9級(jí)特大地震影響市栗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咳短,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一填帽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咙好,春花似錦篡腌、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至层宫,卻和暖如春杨伙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萌腿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工限匣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毁菱。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓米死,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鼎俘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哲身,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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