引用別人十個(gè)字對(duì)棧和堆的總結(jié)
棧是吃了吐 堆是吃了拉
下面進(jìn)入主題為什么要用copy去修飾block呢
個(gè)人理解:默認(rèn)情況下,block會(huì)存檔在棧中(棧是吃了吐),所以block會(huì)在函數(shù)調(diào)用結(jié)束被銷毀,在調(diào)用會(huì)報(bào)空指針異常,如果用copy修飾的話,可以使其保存在堆區(qū)(堆是吃了拉) ,它的生命周期會(huì)隨著對(duì)象的銷毀而結(jié)束的。只要對(duì)象不銷毀,我們就可以調(diào)用在堆中的block。
在了解block為什么要用copy之前,我們要先了解block的三種類型
一 NSGlobalBlock:全局的靜態(tài)block 沒有訪問外部變量 你的block類型就是這種類型(也就是說你的block沒有調(diào)用其他外部變量)
二 NSStackBlock:保存在棧中的block,沒有用copy去修飾并且訪問了外部變量,你的block類型就是這種類型,會(huì)在函數(shù)調(diào)用結(jié)束被銷毀 (需要在MRC)
三 NSMallocBlock 保存在堆中的block 此類型blcok是用copy修飾出來的block 它會(huì)隨著對(duì)象的銷毀而銷毀,只要對(duì)象不銷毀,我們就可以調(diào)用的到在堆中的block。
下面代碼演示
第一種全局的block 這種block不訪問外部的變量,我們?cè)陂_發(fā)中block都會(huì)訪問外部的變量,所以這種block開發(fā)不會(huì)用到,作為一個(gè)了解
void(^testOneBlock)() = ^(){
NSLog(@"我是全局的block");
};
NSLog(@"testOneBlock=%@",testOneBlock);
//控制臺(tái)輸出
2017-06-10 09:45:09.767 ReactiveCocoa[871:14517]
testOneBlock=<__NSGlobalBlock__: 0x1045982d0>//全局block 他會(huì)隨程序銷毀而銷毀
第二種棧區(qū)block 這種block訪問外部變量,我們重點(diǎn)了解的是第二種和第三種,但是必須要在MRC的模式下控制臺(tái)才會(huì)輸出NSStackBlock類型
如何把當(dāng)前類改為MRC:Build phases -> Compile Sources -> 雙擊當(dāng)前類會(huì)彈出輸入框 -> 把-fno-objc-arc復(fù)制粘貼進(jìn)去 -> OK
//需要MRC模式
int a = 5;
void(^testTwoBlock)() = ^(){
NSLog(@"%d",a);
};
NSLog(@"testTwoBlock=%@",testTwoBlock);
//控制臺(tái)輸出
2017-06-10 09:45:09.768 ReactiveCocoa[871:14517]
testTwoBlock= <__NSStackBlock__: 0x7fff5b668770>//棧區(qū)block 函數(shù)調(diào)用完畢就會(huì)銷毀
[testTwoBlock copy] 這樣操作就會(huì)變成堆區(qū)block
第三種堆區(qū)block 這種block是用copy去修飾的 它的生命周期會(huì)隨對(duì)象銷毀而銷毀
int a = 5;
self.block1 = ^(NSString *str, UIColor *color){
NSLog(@"%d",a);
};
NSLog(@"block1=%@",self.block1);
//控制臺(tái)輸出
2017-06-10 10:02:35.107 ReactiveCocoa[1075:19674] block1=<__NSMallocBlock__: 0x60000004ee50>//用copy修飾的不會(huì)函數(shù)調(diào)用完就結(jié)束,隨對(duì)象銷毀才銷毀 這種是在開發(fā)中正確使用block的姿勢(shì)
第三種block在有些情況下會(huì)造成block的循環(huán)引用,我會(huì)寫在下一篇文章中
寫簡(jiǎn)書只是當(dāng)作筆記來寫,如果那里使用的姿勢(shì)不正確呢,歡迎大神來教導(dǎo)正確姿勢(shì)
(我是一個(gè)小菜逼,沒事就是愛裝逼)沒有特別的意思 純屬覺得順口。辛苦啦都看完啦