Block 是一種特殊的數(shù)據(jù)類(lèi)型准脂,默認(rèn)存儲(chǔ)在棧中,若對(duì)Block 進(jìn)行一次Copy 則Block會(huì)進(jìn)入堆中
1.Block訪問(wèn)外部參數(shù)變量
--1.Block中可以訪問(wèn)外界變量姨伟,會(huì)將外界變量Copy一份窑多,供自己訪問(wèn),并不能修改外界變量的值拳芙,同理察藐,由于是Copy一份,則在Blcok調(diào)用之前修改外界參數(shù)的值舟扎,同樣不會(huì)影響到Block內(nèi)部堆參數(shù)的引用分飞,該值只是在Block聲明時(shí)有效
證明block中的參數(shù)是copy進(jìn)該block的堆中
--2.Block 中可以定義和外界同名的變量,并且若在block中定義了和外界同名的變量睹限,在Block中訪問(wèn)的是Block中的變量
2.__block 修飾符
--1.要在Block中修改外界參數(shù)譬猫,需要用__block 修飾該參數(shù)
但是,若在Block中修改了外界變量的值羡疗,會(huì)影響到外界變量的值
--2.__Block 可以防止Block在堆中時(shí)染服,對(duì)外部參數(shù)引用后Retain操作
3.__Block 關(guān)鍵字的實(shí)現(xiàn)原理
將代碼通過(guò) 終端 編譯成 c++代碼后發(fā)現(xiàn),在不加__Block關(guān)鍵字時(shí)叨恨,Block 在底層會(huì)被編譯成結(jié)構(gòu)體肌索,而參數(shù)a 是通過(guò)參數(shù)傳遞進(jìn)結(jié)構(gòu)體函數(shù),并將該參數(shù)特碳,賦值給結(jié)構(gòu)體內(nèi)部的變量a
既 如果沒(méi)有添加__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在棧中闸准,且訪問(wèn)了外界的對(duì)象益愈,不會(huì)對(duì)對(duì)象進(jìn)行retain操作
但是,若block在堆中,且訪問(wèn)了外界對(duì)象蒸其,那么會(huì)外界的對(duì)象進(jìn)行一次retain操作
需要通過(guò)Block_release()函數(shù)在dealloc函數(shù)中對(duì)Block 進(jìn)行釋放 敏释,block中使用到的對(duì)象也都會(huì)收到該消息
在實(shí)際開(kāi)發(fā)中,若在Block 中訪問(wèn)了外界對(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ù)類(lèi)型凭豪。__weak只能在ARC模式下使用,也只能修飾對(duì)象(NSString)晒杈,不能修飾基本數(shù)據(jù)類(lèi)型(int)嫂伞。__block對(duì)象可以在block中被重新賦值,__weak不可以桐智。