ios - Block小結(jié)

對(duì)于經(jīng)常使用的Block愧旦,你不得不知的東東~~~
先上菜,看看最原始的block使用

int i = 0;
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //1.block的定義,block就是變量名
        int (^block)(int,int);
        //2.block的實(shí)現(xiàn), 可以直接將實(shí)現(xiàn)的代碼寫在其他的函數(shù)或者方法中杆怕,函數(shù)指針不可以
        block = ^int(int a, int b){
            return  a + b;
        };
        //3.block的調(diào)用
       int  r =  block(3,4);
        NSLog(@"r =%d",r);
        //4.block的使用的注意點(diǎn)族购。
        //4.1 block和局部變量
        __block int a = 10;
        int (^block1)(int) = ^int(int b){//定義和實(shí)現(xiàn)一起寫
            //a = 100;block默認(rèn)情況下不可以修改外部的局部變量,若要修改加關(guān)鍵字__block
            a = 90;
            
            return a + b;//block內(nèi)部可以直接使用外部的變量
        };
        int r2 = block1(2);
        NSLog(@"%d",r2);
        //4.2block和全局變量
        int(^block3)(int) = ^int(int a){
            i = 9;
            return a + i;
        };
        r = block3(10);
        NSLog(@"r = %d",r);
        //5.block的其它寫法
        //5.1實(shí)現(xiàn)block的時(shí)候返回子=值類型可以不寫
        int (^block4)(int) = ^(int a){
            return a;
        };
        r = block4(20);
        NSLog(@"r =%d",r);
        //5.2沒有參數(shù)的時(shí)候陵珍,實(shí)現(xiàn)block的時(shí)候()可以省略
        int (^block5)() = ^{
            
            return 100;
        };
        r = block5();
        NSLog(@"%d",r);
        
        
        
        
        
    }
    return 0;
}

block的實(shí)質(zhì)是什么寝杖?一共有幾種block?都是什么情況下生成的互纯?

閉包是什么瑟幕?閉包是一個(gè)函數(shù)(或指向函數(shù)的指針),再加上該函數(shù)執(zhí)行的外部的上下文變量(自由變量)留潦。Block 就是 Objective-C 對(duì)于閉包的對(duì)象實(shí)現(xiàn)只盹。即,Block 的實(shí)質(zhì)是對(duì)象兔院。為什么說 Block 是一個(gè)對(duì)象呢殖卑,原因就在于 isa 指針。在 Block_layout 的數(shù)據(jù)結(jié)構(gòu)定義里坊萝,有 isa 指針懦鼠。所有的對(duì)象都有 isa 指針,用于實(shí)現(xiàn)對(duì)象相關(guān)功能

有3中類型的block

全局 Block:_NSConcreteGlobalBlock
全局 Block 的結(jié)構(gòu)體實(shí)例設(shè)置在程序的數(shù)據(jù)存儲(chǔ)區(qū)屹堰,所以可以在程序的任意位置通過指針來訪問肛冶。_NSConcreteGlobalBlock 是全局的 Block,在編譯期間就已經(jīng)決定了扯键,如同宏一樣睦袖。
以下 2 個(gè)條件只要滿足 1 個(gè)就可以產(chǎn)生全局 Block:
? 記述全局變量的地方有 Block 語法時(shí)。
? Block 不截獲自動(dòng)變量時(shí)荣刑。
棧 Block:_NSConcreteStackBlock
生成 Block 后馅笙,如果這個(gè) Block 不是全局 Block,那么它就是 _NSConcreteStackBlock 對(duì)象厉亏,但是如果其所屬的變量作用域結(jié)束董习,該 Block 就被廢棄。
如果 Block 變量用 __block 復(fù)制到了堆上爱只,則不會(huì)再收到變量作用域結(jié)束的影響皿淋,因?yàn)樗兂闪硕?Block。
堆 Block:_NSConcreteMallocBlock
將棧 Block 復(fù)制到堆以后恬试,Block 結(jié)構(gòu)體的 isa 成員變量變成了 _NSConcreteMallocBlock窝趣。
大多數(shù)情況下,編譯器會(huì)進(jìn)行判斷训柴,自動(dòng)將 Block 從棧復(fù)制到堆:
? Block 作為函數(shù)值返回的時(shí)候
? 部分情況下哑舒,向方法或者函數(shù)中傳遞 Block 的時(shí)候
o Cocoa 框架的方法且方法名中含有 usingBlock 等時(shí)
o GCD 的 API
除來這 2 種情況,基本都需要我們手動(dòng)復(fù)制 Block幻馁。

為什么在默認(rèn)情況下無法修改被block捕獲的變量洗鸵? __block都做了什么越锈?
? 默認(rèn)情況下,Block 里面的變量膘滨,拷貝進(jìn)去的是變量的值瞪浸,而不是指向變量的內(nèi)存指針。
? 當(dāng)使用 __block 修飾后的變量吏祸,拷貝到 Block 里面的就是指向變量的指針对蒲,就可以修改變量的值。
注意: MRC贡翘,如果沒有用 __block蹈矮,會(huì)對(duì)外部對(duì)象采用 copy 操作,而用了 __block 則不會(huì)采用 copy 操作鸣驱。

  1. MRC泛鸟,__block 根本不會(huì)對(duì)指針?biāo)赶虻膶?duì)象進(jìn)行 copy 操作,只是把指針進(jìn)行復(fù)制踊东。
  2. ARC北滥,對(duì)應(yīng)聲明為 __block 的外部對(duì)象,Block 內(nèi)部會(huì)進(jìn)行 retain闸翅,以至于在 Block 環(huán)境內(nèi)能安全引用外部對(duì)象再芋。
    解決方式
    1。 __block 修飾符坚冀,用于指定將改變變量的存儲(chǔ)區(qū)域(從棧到堆)2济赎。 改變存儲(chǔ)于特殊存儲(chǔ)區(qū)域的變量(全局變量、靜態(tài)全局變量记某、靜態(tài)變量)

block的內(nèi)存管理
? 無論當(dāng)前環(huán)境是ARC還是MRC,只要block沒有訪問外部變量,block始終在全局區(qū)
? MRC情況下
? block如果訪問外部變量,block在棧里
? 不能對(duì)block使用retain,否則不能保存在堆里
? 只有使用copy,才能放到堆里
? ARC情況下
? block如果訪問外部變量,block在堆里
? block可以使用copy和strong,并且block是一個(gè)對(duì)象
? 為什么用copy修飾
? 為什么要用copy修飾司训,這是因?yàn)樵贛RC時(shí)期,作為屬性的block在初始化時(shí)是被存放在靜態(tài)區(qū)的液南,這樣在使用時(shí)如果block內(nèi)有調(diào)用外部變量壳猜,那么block無法保留其內(nèi)存,在初始化的作用域內(nèi)使用并不會(huì)有什么影響滑凉,但一但出了block的初始化作用域统扳,就會(huì)引起崩潰,使用copy可以將block的內(nèi)存推入堆中譬涡,這樣讓其擁有保存調(diào)用的外部變量的內(nèi)存的能力闪幽。

block的注意點(diǎn)

1)在block內(nèi)部使用外部指針且會(huì)造成循環(huán)引用情況下,需要用__weak修飾外部指針
  __weak typeof(self) weakSelf = self;

2)在block內(nèi)部如果調(diào)用了延時(shí)函數(shù)還使用弱指針會(huì)取不到該指針,因?yàn)橐呀?jīng)被銷毀了,需要在block內(nèi)部再將弱指針重新強(qiáng)引用一下
__strong typeof(self) strongSelf = weakSelf;

3)如果需要在block內(nèi)部改變外部變量的話,需要在用__block修飾外部變量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市涡匀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溉知,老刑警劉巖陨瘩,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腕够,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡舌劳,警方通過查閱死者的電腦和手機(jī)帚湘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甚淡,“玉大人大诸,你說我怎么就攤上這事」嶝裕” “怎么了资柔?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)撵割。 經(jīng)常有香客問我贿堰,道長(zhǎng),這世上最難降的妖魔是什么啡彬? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任羹与,我火速辦了婚禮,結(jié)果婚禮上庶灿,老公的妹妹穿的比我還像新娘纵搁。我一直安慰自己,他們只是感情好往踢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布诡渴。 她就那樣靜靜地躺著,像睡著了一般菲语。 火紅的嫁衣襯著肌膚如雪妄辩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天山上,我揣著相機(jī)與錄音眼耀,去河邊找鬼。 笑死佩憾,一個(gè)胖子當(dāng)著我的面吹牛哮伟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妄帘,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼楞黄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了抡驼?” 一聲冷哼從身側(cè)響起鬼廓,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎致盟,沒想到半個(gè)月后碎税,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尤慰,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年雷蹂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伟端。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡匪煌,死狀恐怖责蝠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萎庭,我是刑警寧澤霜医,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站擎椰,受9級(jí)特大地震影響支子,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜达舒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一值朋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巩搏,春花似錦昨登、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至禽捆,卻和暖如春笙什,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胚想。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工琐凭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浊服。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓统屈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親牙躺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子愁憔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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