由三個(gè)面試題引起的block總結(jié)

block.jpg

iOS開發(fā)中磷箕,block的使用還是挺頻繁的尝江,不管是自定義還是系統(tǒng)提供的很多block函數(shù)吠昭。但是抽絲剝繭的事還是發(fā)生在面試中傲隶,面試的時(shí)候block被提問(wèn)的概率還是挺高的饺律。
   以下根據(jù)面試題做出對(duì)block部分知識(shí)點(diǎn)的講解,僅代表個(gè)人看法跺株,如果有錯(cuò)誤复濒,請(qǐng)指出脖卖。
看題之前,先了解一下block類型:

分NSConcreteGlobalBlock
NSConcreteStackBlock
NSConcreteMallocBlock分別在全局變量區(qū)巧颈,棧區(qū)畦木,堆區(qū)。

_NSConcreteGlobalBlock類型的block要么是空block砸泛,要么是不訪問(wèn)任何外部變量的block十籍。它既不在棧中,也不在堆中唇礁,我理解為它可能在內(nèi)存的全局區(qū)勾栗。(配置在全局變量上的Block,從變量作用域外也可以通過(guò)指針安全地使用)
舉例:

    void(^ blockA)() = ^{
        NSLog(@"just a block");
    };

_NSConcreteStackBlock類型的block有閉包行為盏筐,也就是有訪問(wèn)外部變量围俘,并且該block只且只有有一次執(zhí)行,因?yàn)闂V械目臻g是可重復(fù)使用的机断,所以當(dāng)棧中的block執(zhí)行一次之后就被清除出棧了楷拳,所以無(wú)法多次使用。
舉例:

下邊這個(gè)例子吏奸,如果在ARC下創(chuàng)建欢揖,blockC會(huì)創(chuàng)建在堆上,如果在MRC 環(huán)境下創(chuàng)建會(huì)創(chuàng)建在棧上奋蔚。
  int value = 10;
    void(^ blockC)() = ^{
        NSLog(@"just a block === %d", value);
    };

_NSConcreteMallocBlock類型的block有閉包行為她混,并且該block需要被多次執(zhí)行。當(dāng)需要多次執(zhí)行時(shí)泊碑,就會(huì)把該block從棧中復(fù)制到堆中坤按,供以多次執(zhí)行。
舉例:

void addBlockToArray(NSMutableArray *array) {
    char b = 'B';
    [array addObject:^{
            printf("%c\n", b);
    }];
}
void exampleB() {
    NSMutableArray *array = [NSMutableArray array];
    addBlockToArray(array);
    void (^block)() = [array objectAtIndex:0];
    block();
}
addBlockToArray中的block還在棧區(qū)馒过,exampleB中的block被復(fù)制到了堆區(qū)變成了NSConcreteMallocBlock臭脓。

提問(wèn)的第一個(gè)問(wèn)題如下:

1,下面代碼在按鈕點(diǎn)擊后腹忽,在ARC下會(huì)發(fā)生什么来累,MRC下呢?為什么窘奏?

@property(nonatomic, assign) void(^block)();

- (void)viewDidLoad {
    [superviewDidLoad];
    int value = 10;
    void(^blockC)() = ^{
        NSLog(@"just a block === %d", value);
    };

    NSLog(@"%@", blockC);
    _block = blockC;

}

- (IBAction)action:(id)sender {
    NSLog(@"%@", _block);
}

經(jīng)測(cè)試嘹锁,在ARC環(huán)境下是不會(huì)崩潰的,在MRC環(huán)境下因?yàn)樵L問(wèn)已經(jīng)釋放的對(duì)象着裹,程序崩潰领猾。個(gè)人給出的解釋是,在ARC環(huán)境下,創(chuàng)建的blockC 摔竿,blockC是在堆區(qū)面粮,MRC環(huán)境下blockC是在棧區(qū),棧區(qū)在函數(shù)返回以后就銷毀拯坟,再次訪問(wèn)的時(shí)候就會(huì)引起訪問(wèn)已經(jīng)銷毀的對(duì)象但金。
注:此處之前搜到的答案是這樣的:@property(nonatomic, assign) void(^block)(); 在ARC環(huán)境下,不管用assign,copy還是strong來(lái)修飾block都會(huì)被copy到堆區(qū)郁季,所以block不會(huì)因?yàn)楹瘮?shù)的返回而銷毀冷溃。在MRC環(huán)境下必須用copy然后調(diào)用點(diǎn)語(yǔ)法賦值(self.block = blockC),block 就會(huì)從棧區(qū)copy到堆區(qū)梦裂。
但是實(shí)際測(cè)試結(jié)果如下:

   int a =0;
    self.block=^{
        NSLog(@"aaa%d",a);
    };
    
    NSLog(@"aaa");

結(jié)果顯示


顯示在棧區(qū).png

  所以個(gè)人認(rèn)為似枕,上邊block在ARC環(huán)境下沒(méi)有銷毀,是因?yàn)閎lockC在堆區(qū)年柠,而不是說(shuō)ARC環(huán)境下assign修飾的block被copy到了堆區(qū)凿歼。
因此不管在MRC 還是ARC 定義成屬性的block要用copy防止過(guò)早銷毀。

2冗恨,在ARC環(huán)境下這段代碼為什么不會(huì)崩潰答憔?

@property(nonatomic, weak) void(^block)();

- (void)viewDidLoad {
    [super viewDidLoad];

    void(^ __weak blockA)() = ^{
        NSLog(@"just a block");
    };

    _block = blockA;

}

- (IBAction)action:(id)sender {
    _block();
}

經(jīng)過(guò)測(cè)試blockA是在全局變量區(qū),類型是NSConcreteGlobalBlock前邊注意到(配置在全局變量上的Block掀抹,從變量作用域外也可以通過(guò)指針安全地使用)虐拓。

在全局變量區(qū).png

在MRC環(huán)境直接寫報(bào)錯(cuò),需要將 _weak做處理傲武,不做深究梢杭。
注:在第一題中我們發(fā)現(xiàn)慨蓝,直接創(chuàng)建的block是在堆區(qū)的往弓,但是經(jīng)過(guò)__weak修飾后會(huì)放在棧區(qū)笛坦。

下面代碼中為什么可以直接用self?
[UIView animateWithDuration:1 animations:^{
    self.view.backgroundColor = [UIColor yellowColor];
}];

下面這段代碼可以用self嗎疟位?為什么瞻润?
- (void)doSomething {
    [BlockClass doSomethingUseBlock:^{
        NSLog(@"%@", self);
    }];
}

關(guān)于第一個(gè)問(wèn)題,我們會(huì)發(fā)現(xiàn)甜刻,在很多情況下绍撞,block中使用self不會(huì)引起循環(huán)引用問(wèn)題,這首先罢吃,我們要搞明白什么是循環(huán)引用,就是當(dāng)前類持有強(qiáng)引用這個(gè)block昭齐,然后在block中又強(qiáng)引用了當(dāng)前類尿招,彼此等待都不能銷毀。但是UIView是一個(gè)類,當(dāng)前控制器不可能強(qiáng)引用一個(gè)類就谜,所以當(dāng)前控制器沒(méi)有強(qiáng)引用這個(gè)block怪蔑,循環(huán)不成立。(第二個(gè)問(wèn)題也就回答了)
此處拓展丧荐,在AFN中也是在block中使用self缆瓣,他是進(jìn)行了特殊處理,原理可以自己去搜一下虹统。系統(tǒng)GCD是在結(jié)束的時(shí)候?qū)?duì)象都進(jìn)行了釋放弓坞。

以下補(bǔ)充知識(shí)點(diǎn):

補(bǔ)充1. 關(guān)于block中變量修改引起的思考。
我們知道block中是不能直接修改外部變量的车荔,必須經(jīng)過(guò)_block修飾渡冻。原因是:block不允許修改的是棧中指針的內(nèi)存地址,__block的作用是將棧中的地址放到堆中,這樣就可以修改了。
補(bǔ)充2. 關(guān)于block中使用weak和strong修飾詞
首先我們知道忧便,為了防止循環(huán)引用族吻,我們會(huì)使用weak來(lái)修飾self,防止產(chǎn)生強(qiáng)引用,但是在很多框架中我們會(huì)發(fā)現(xiàn)珠增,block中還會(huì)有strong修飾詞超歌,這是防止block還在執(zhí)行的時(shí)候,別的地方把self給釋放了蒂教。找一個(gè)別人寫好的例子

 第一步:我們自定義一個(gè)類巍举,在該類dealloc方法中加一行打印語(yǔ)句;

@interface SampleObject :NSObject

@end

@implementation SampleObject

- (void)dealloc{

NSLog(@"dealloc %@",[self class]); 

}

@end

第二步:實(shí)例化該類悴品,并在block中調(diào)用它禀综;(沒(méi)有加strong修飾符,三秒后釋放該對(duì)象)

SampleObject* sample = [[SampleObject alloc]init];

self->sample= sample;

__weakSampleObject* weaksample = self->sample;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

NSIntegercount =0;

//__strong SampleObject* strongsample = weaksample;

while(count<10) {

count++;

NSLog(@"aaa %@",weaksample);

sleep(1);

}

});

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

self->sample=nil;

});

打印結(jié)果如下(沒(méi)有用strong修飾符的打印結(jié)果如下):

輸出.png

結(jié)論是:如果僅僅使用__weak去修飾變量苔严,當(dāng)別處把變量釋放后定枷,block中該變量也會(huì)被釋放掉。
那么好届氢,我們?cè)诎训诙街械姆椒ㄐ薷囊幌虑分希由蟬trong修飾符:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

__strongSampleObject* strongsample = weaksample;

NSIntegercount =0;

while(count<10) {

count++;

NSLog(@"aaa %@",strongsample);

sleep(1);

}

});

打印結(jié)果如下:


加strong輸出.png

結(jié)論是當(dāng)加上修飾符strong時(shí),當(dāng)別處把變量釋放掉退子,但調(diào)用該變量的block如果仍然沒(méi)有執(zhí)行結(jié)束岖妄,那么系統(tǒng)就會(huì)等待block執(zhí)行完成后再釋放,對(duì)該變量在block中的使用起到了保護(hù)作用寂祥。當(dāng)block執(zhí)行結(jié)束后會(huì)自動(dòng)釋放掉荐虐。

繼續(xù)整理補(bǔ)充,丸凭,福扬,腕铸,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铛碑,隨后出現(xiàn)的幾起案子狠裹,更是在濱河造成了極大的恐慌,老刑警劉巖汽烦,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涛菠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡撇吞,警方通過(guò)查閱死者的電腦和手機(jī)俗冻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)梢夯,“玉大人言疗,你說(shuō)我怎么就攤上這事∷淘遥” “怎么了噪奄?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)人乓。 經(jīng)常有香客問(wèn)我勤篮,道長(zhǎng),這世上最難降的妖魔是什么色罚? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任碰缔,我火速辦了婚禮,結(jié)果婚禮上戳护,老公的妹妹穿的比我還像新娘金抡。我一直安慰自己,他們只是感情好腌且,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布梗肝。 她就那樣靜靜地躺著,像睡著了一般铺董。 火紅的嫁衣襯著肌膚如雪巫击。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天精续,我揣著相機(jī)與錄音坝锰,去河邊找鬼。 笑死重付,一個(gè)胖子當(dāng)著我的面吹牛顷级,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播确垫,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼弓颈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拣凹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起恨豁,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爬迟,沒(méi)想到半個(gè)月后橘蜜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡付呕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年计福,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徽职。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡象颖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姆钉,到底是詐尸還是另有隱情说订,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布潮瓶,位于F島的核電站陶冷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毯辅。R本人自食惡果不足惜埂伦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望思恐。 院中可真熱鬧沾谜,春花似錦、人聲如沸胀莹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗜逻。三九已至涩僻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栈顷,已是汗流浹背逆日。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萄凤,地道東北人室抽。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像靡努,于是被迫代替她去往敵國(guó)和親坪圾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晓折,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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

  • 《Objective-C高級(jí)編程》這本書就講了三個(gè)東西:自動(dòng)引用計(jì)數(shù)、block兽泄、GCD漓概,偏向于從原理上對(duì)這些內(nèi)容...
    WeiHing閱讀 9,838評(píng)論 10 69
  • 前言 Blocks是C語(yǔ)言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,774評(píng)論 0 23
  • Block 梳理與疑問(wèn) 時(shí)隔一年病梢,再次讀 《Objective-C 高級(jí)編程》胃珍,看到 block 一章,這一次從頭...
    DeerRun閱讀 642評(píng)論 0 2
  • 把網(wǎng)上的一些結(jié)合自己面試時(shí)遇到的面試題總結(jié)了一下蜓陌,以后有新的還會(huì)再加進(jìn)來(lái)觅彰。 1. OC 的理解與特性 OC 作為一...
    AlaricMurray閱讀 2,569評(píng)論 0 20
  • 一、HTML钮热、XML填抬、XHTML 有什么區(qū)別 HTML,全名為超文本標(biāo)記語(yǔ)言(Hyper Text Marku...
    select_yang閱讀 180評(píng)論 0 0