默認(rèn)情況下艘刚,在block中訪問的外部變量是復(fù)制過去的,即:寫操作不對原變量生效截珍。但是你可以加上__block
__block int a = 0;
void (^foo)(void) = ^{
a = 1;
};
foo(); //這里攀甚,a的值被修改為1
Block不允許修改外部變量的值箩朴,這里所說的外部變量的值,指的是棧中指針的內(nèi)存地址秋度。__block 所起到的作用就是只要觀察到該變量被 block 所持有炸庞,就將“外部變量”在棧中的內(nèi)存地址放到了堆中。進而在block內(nèi)部也可以修改外部變量的值荚斯。
為什么從棧到堆就可以修改了呢埠居?
block默認(rèn)的是NSGlobalBlock類似于函數(shù),存放在代碼段;當(dāng)block內(nèi)部使用了外部的變量時事期,block的存放位置變成了NSMallockBlock(堆),所以用__block修飾后才可以在block內(nèi)部直接修改該變量
Block其實包含兩個部分內(nèi)容
- Block執(zhí)行的代碼滥壕,這是在編譯的時候已經(jīng)生成好的;
- 一個包含Block執(zhí)行時需要的所有外部變量值的數(shù)據(jù)結(jié)構(gòu)。 Block將使用到的兽泣、作用域附近到的變量的值建立一份快照拷貝到棧上绎橘。
Block與函數(shù)另一個不同是,Block類似ObjC的對象唠倦,可以使用自動釋放池管理內(nèi)存
Block的類型與內(nèi)存管理
根據(jù)Block在內(nèi)存中的位置分為三種類型NSGlobalBlock金踪,NSStackBlock, NSMallocBlock。
- NSGlobalBlock:類似函數(shù)牵敷,位于text段胡岔;
- NSStackBlock:位于棧內(nèi)存,函數(shù)返回后Block將無效枷餐;
- NSMallocBlock:位于堆內(nèi)存靶瘸。