Block 是一種特殊的數(shù)據(jù)類型,默認(rèn)存儲(chǔ)在棧中,若對(duì)Block 進(jìn)行一次Copy 則Block會(huì)進(jìn)入堆中
1.Block訪問外部參數(shù)變量
--1.Block中可以訪問外界變量,會(huì)將外界變量Copy一份,供自己訪問,并不能修改外界變量的值,同理,由于是Copy一份,則在Blcok調(diào)用之前修改外界參數(shù)的值,同樣不會(huì)影響到Block內(nèi)部堆參數(shù)的引用,該值只是在Block聲明時(shí)有效

證明block中的參數(shù)是copy進(jìn)該block的堆中
--2.Block 中可以定義和外界同名的變量,并且若在block中定義了和外界同名的變量,在Block中訪問的是Block中的變量
2.__block 修飾符
--1.要在Block中修改外界參數(shù),需要用__block 修飾該參數(shù)
但是,若在Block中修改了外界變量的值,會(huì)影響到外界變量的值

--2.__Block 可以防止Block在堆中時(shí),對(duì)外部參數(shù)引用后Retain操作
3.__Block 關(guān)鍵字的實(shí)現(xiàn)原理

將代碼通過 終端 編譯成 c++代碼后發(fā)現(xiàn),在不加__Block關(guān)鍵字時(shí),Block 在底層會(huì)被編譯成結(jié)構(gòu)體,而參數(shù)a 是通過參數(shù)傳遞進(jìn)結(jié)構(gòu)體函數(shù),并將該參數(shù),賦值給結(jié)構(gòu)體內(nèi)部的變量a
既 如果沒有添加__block 關(guān)鍵字聲明變量 該變量是值傳遞

內(nèi)部函數(shù)的調(diào)用

a變量的具體引用
添加__block關(guān)鍵字 后是對(duì)a變量地址的引用

添加__block關(guān)鍵字后,是對(duì)a變量地址的引用

4.MRC中的Block引用計(jì)數(shù)
默認(rèn)情況下block 存儲(chǔ)在棧中,如果對(duì)block 進(jìn)行一個(gè)copy操作,block 會(huì)轉(zhuǎn)移到堆中,
若block在棧中,且訪問了外界的對(duì)象,不會(huì)對(duì)對(duì)象進(jìn)行retain操作
但是,若block在堆中,且訪問了外界對(duì)象,那么會(huì)外界的對(duì)象進(jìn)行一次retain操作
需要通過Block_release()函數(shù)在dealloc函數(shù)中對(duì)Block 進(jìn)行釋放 ,block中使用到的對(duì)象也都會(huì)收到該消息
在實(shí)際開發(fā)中,若在Block 中訪問了外界對(duì)象,一定要給變量添加__block 修飾符,這樣哪怕Block在堆中,也不會(huì)對(duì)外界對(duì)象進(jìn)行Retain
5.copy Block 引發(fā)的循環(huán)引用
--1.MRC下
在堆中的Block內(nèi),引用自己對(duì)象本身,形成循環(huán)引用 利用 __block 修飾對(duì)象,在block內(nèi)不會(huì)進(jìn)行retain

--2.ARC
在ARC環(huán)境中同理,被Copy的Block 在堆中,會(huì)對(duì)引用的外界參數(shù)進(jìn)行強(qiáng)引用,這個(gè)時(shí)候需要將傳入Block內(nèi)的對(duì)象,轉(zhuǎn)化為若引用即可
Friend *p = [[Friend alloc]init];
下面這兩句代碼任選一句就可以了,但是官方推薦選用第一句
__weak typeof (p) weakp = p;
__unsafe_unretained typeof (p) weaka = p ;
p.testBlock =^{
[weakp run];
};
總結(jié)
1:什么是block?
block其實(shí)就是一個(gè)代碼塊,把你想要執(zhí)行的代碼封裝在這個(gè)代碼塊里,等到需要的時(shí)候再去調(diào)用。那block是OC對(duì)象嗎?答案是肯定的
官方文檔如下
2:block要用copy修飾,還是用strong
block本身是像對(duì)象一樣可以retain,和release。但是,block在創(chuàng)建的時(shí)候,它的內(nèi)存是分配在棧(stack)上,而不是在堆(heap)上。他本身的作于域是屬于創(chuàng)建時(shí)候的作用域,一旦在創(chuàng)建時(shí)候的作用域外面調(diào)用block將導(dǎo)致程序崩潰。
使用retain也可以,但是block的retain行為默認(rèn)是用copy的行為實(shí)現(xiàn)的,
因?yàn)閎lock變量默認(rèn)是聲明為棧變量的,為了能夠在block的聲明域外使用,所以要把block拷貝(copy)到堆,所以說(shuō)為了block屬性聲明和實(shí)際的操作一致,最好聲明為copy。
3:__block關(guān)鍵字的使用
在Block的{}體內(nèi),是不可以對(duì)外面的變量進(jìn)行更改的,使用__block就能改變block塊中變量的值
4:__block和__weak有什么區(qū)別?
__block不管是ARC還是MRC模式下都可以使用,可以修飾對(duì)象,還可以修飾基本數(shù)據(jù)類型。__weak只能在ARC模式下使用,也只能修飾對(duì)象(NSString),不能修飾基本數(shù)據(jù)類型(int)。__block對(duì)象可以在block中被重新賦值,__weak不可以。