Block底層原理
block本身也是一個(gè)oc對(duì)象琴拧,他內(nèi)部有一個(gè)isa指針踩衩。 block可以捕獲局部變量责静,對(duì)于全局不需要捕獲墨缘,所以在block內(nèi)部可以修改auto星虹,static全局變量的原因。在局部又分為auto/static镊讼,對(duì)于static宽涌,block捕獲的是指針,也就是變量的地址蝶棋,而對(duì)于auto變量block捕獲的是值卸亮,注意是變量的值。這就是為什么不能修改block外部auto變量的原因玩裙。如下列子
int a = 1000;
static int b = 200;
void (^block)(NSString *) = ^(NSString * name){
nslog(@"%d-%d",a , b);
}
a = 1000000;
b = 300;
block("g");//最后打印 1000 - 300兼贸;
你會(huì)發(fā)現(xiàn)a的值沒有修改成功,為什么這樣吃溅,其實(shí)就是上面所講溶诞,auto修飾的,是將a變量當(dāng)參數(shù)傳遞給block决侈,但是僅僅是傳值螺垢,而static修飾的變量,是傳遞的地址赖歌,所以能修改值枉圃。
如果轉(zhuǎn)成c++文件,在終端用clang打開源碼俏站,就能看見讯蒲,內(nèi)部有一個(gè)__main_block_impl_0的結(jié)構(gòu)體,而我們auto修飾的變量a肄扎,是從impl.FuncPtr == 獲取的墨林,所以就算你將a的值從新賦值,最終還是從impl.FuncPtr 取值犯祠,所以就不能修改成功旭等。如果想要修改成功,我們只需要在變量前面加上__block就是衡载,這樣修飾后搔耕,其實(shí)就是講他包裝成一個(gè)對(duì)象處理的。
block分為global,malloc弃榨,static三種類型菩收,分別位于內(nèi)存數(shù)據(jù)區(qū)、堆區(qū)鲸睛、棧區(qū)娜饵。
怎么區(qū)分呢,捕獲外部auto就是static官辈,沒有就是global箱舞,如果進(jìn)行了copy操作就是malloc類型block。位于棧上的block一般在函數(shù)作用域后就被銷毀了拳亿,只有為進(jìn)行了copy操作晴股,引用計(jì)數(shù)加1,不會(huì)銷毀肺魁,這就是為什么mrc時(shí)候电湘,調(diào)用block會(huì)報(bào)錯(cuò),需要手動(dòng)進(jìn)行copy操作万搔,在arc不會(huì)胡桨,是因?yàn)橄到y(tǒng)替我們加了copy操作。