block內(nèi)部為什么不能夠直接修改 auto 變量的值?
因?yàn)?auto age 變量是在棧上存放的, 當(dāng)函數(shù)作用域結(jié)束時(shí)就會(huì)被銷(xiāo)毀,而 block 執(zhí)行的函數(shù)是在另一個(gè)函數(shù)方法里, 這個(gè)函數(shù)是無(wú)法訪問(wèn)到 auto age 變量的 ,雖然 block內(nèi)部也會(huì)生成一個(gè)一模一樣的變量 age 但是這個(gè) age變量 是 block 內(nèi)部的 不會(huì)影響到外部的 auto 變量 age . 因此 block 內(nèi)部是無(wú)法去修改
怎么樣才能在 block 內(nèi)部去修改局部變量的值呢 ?
有兩種方法可以修改到 變量 age 的值 ,第一種 用static 修飾 age 變量 ,由于是靜態(tài)變量 它會(huì)存放在一個(gè) .data區(qū) 這塊的內(nèi)存是隨著應(yīng)用的生命周期而結(jié)束,這樣就造成了 age 這個(gè)變量 無(wú)法被釋放掉
第二種方法 就是用 __block 去修飾 age 變量,即不改變 age 是 auto 類(lèi)型的變量 又可以在 block 內(nèi)部去修改 age 的值 .
__block是怎么實(shí)現(xiàn)對(duì)局部變量的修改呢?
帶著這個(gè)問(wèn)題 我們將這段代碼轉(zhuǎn)成C++的代碼 一窺究竟
void testBlock() {
去掉一些強(qiáng)制類(lèi)型轉(zhuǎn)換后 簡(jiǎn)化為下邊的代碼
MyBlock block;
__Block_byref_age_0 age = {0,&age, 0, sizeof(__Block_byref_age_0), 10};
block = &__testBlock_block_impl_0(__testBlock_block_func_0, &__testBlock_block_desc_0_DATA,&age, 570425344));
block->FuncPtr)(block);
}
///Block 內(nèi)部結(jié)構(gòu) 不再是 int age 而是 __Block_byref_age_0 *age
struct __testBlock_block_impl_0 {
struct __block_impl impl;
struct __testBlock_block_desc_0* Desc;
__Block_byref_age_0 *age; // by ref
__testBlock_block_impl_0(void *fp, struct __testBlock_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
__Block_byref_age_0 其實(shí)也是一個(gè)OC對(duì)象 內(nèi)部有 isa 指針
struct __Block_byref_age_0 {
void *__isa; ///表示它是一個(gè)OC對(duì)象
__Block_byref_age_0 *__forwarding; ///一個(gè)指向自身的結(jié)構(gòu)體指針
int __flags;
int __size; ///內(nèi)存大小
int age; ///外部 auto 變量age的值
};
__Block_byref_age_0 age = {0,&age, 0, sizeof(__Block_byref_age_0), 10};
同過(guò) block 內(nèi)部的 age -> __forwarding指針 -> age 去修改 age 的值
static void __testBlock_block_func_0(struct __testBlock_block_impl_0 *__cself) {
__Block_byref_age_0 *age = __cself->age; // bound by ref
///同過(guò) block 內(nèi)部的 age -> __forwarding指針 -> age 去修改 age 的值
(age->__forwarding->age) = 20;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_hj_pwgsq9614nb0vq4zd315tcx80000gn_T_main_163d3b_mi_0,(age->__forwarding->age));
}