Block中使用__block變量的情況
</br>
Block要修改值的第二種方法:使用__block說(shuō)明符
艇搀,全稱(chēng)為__block存儲(chǔ)域類(lèi)說(shuō)明符
刊殉。C語(yǔ)言中有以下存儲(chǔ)域類(lèi)說(shuō)明符:
- typedef
- extern
- static
- auto
- register
__block
說(shuō)明符類(lèi)似于static
、auto
和register
說(shuō)明符炮车,它們用于指定將變量值設(shè)置到哪個(gè)存儲(chǔ)域中舵变。例如酣溃,auto
表示作為自動(dòng)變量存儲(chǔ)在棧中,static
表示作為靜態(tài)變量存儲(chǔ)在數(shù)據(jù)區(qū)中纪隙。以下是分析例子:
Objective-C
__block int val = 10;
void (^blk)(void) = ^{ val = 1; };
C++
struct __Block_byref_val_0 {
void *__isa;
__Block_byref_val_0 *__forwarding;
int __flags;
int __size;
int val;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0 *Desc;
__Block_byref_val_0 *val;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val, int flags=0) : val(_val->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_val_0 *val = __cself->val;
(val->__forwarding->val) = 1;
}
static void __main_block_copy_0 (struct __main_block_impl_0 *dst, struct __main_block_impl_0 *src) {
_Block_object_assign(&dst->val, src->val, BLOCK_FIELD_IS_BYREF);
}
static void __main_block_dispose_0(struct __main_block_impl_0 *src) {
_Block_object_dispose(src->val, BLOCK_FIELD_IS_BYREF);
}
static struct __main_block_desc_0 {
unsigned long reserved;
unsigned long Block_size;
void (*copy)(struct __main_block_impl_0 *, struct __main_block_impl_0 *);
void (*dispose)(struct __main_block_impl_0 *);
} __main_block_desc_0_DATA = {
0,
sizeof(struct __main_block_impl_0),
__main_block_copy_0,
__main_block_dispose_0
};
int main() {
__Block_byref_val_0 val = {
0,
&val,
0,
sizeof(__Block_byref_val_0),
10
};
blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);
return 0;
}
新增的部分以粉紅色顯示赊豌。
從圖中看到,__block變量
被轉(zhuǎn)換為_Block_byref_val_0
結(jié)構(gòu)體绵咱,Block的成員變量有一個(gè)指向該結(jié)構(gòu)體的指針碘饼。Block成員變量保留指針而不是一個(gè)結(jié)構(gòu)體的設(shè)計(jì),是為了能夠在多個(gè)Block使用__block變量
悲伶。下面是說(shuō)明這個(gè)問(wèn)題的例子艾恼。
__block int val = 10;
void (^blk0)(void) = ^{ val = 0;};
void (^blk1)(void) = ^{ val = 1;};
__Block_byref_val_0 val = {
0,
&val,
0,
sizeof(__Block_byref_val_0),
10
};
blk0 = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &val, 0x22000000);
blk1 = &__main_block_impl_1(__main_block_func_1, &__main_block_desc_1_DATA, &val, 0x22000000);
兩個(gè)Block都使用了__Block_byref_val_0
結(jié)構(gòu)體實(shí)例val
的指針。這樣一來(lái)就可以從多個(gè)Block中使用同一個(gè)__block變量
麸锉。當(dāng)然钠绍,反過(guò)來(lái)從一個(gè)Block中使用多個(gè)__block變量
也沒(méi)有問(wèn)題。只要增加Block的結(jié)構(gòu)體成員變量與構(gòu)造函數(shù)的參數(shù)花沉,便可對(duì)應(yīng)使用多個(gè)__block變量
柳爽。
Block數(shù)據(jù)結(jié)構(gòu)圖(6)中Desc
新增的兩個(gè)函數(shù)指針,copy函數(shù)用于?復(fù)制Block碱屁,dispose函數(shù)用于廢棄Block磷脯。
上例的int型__block變量轉(zhuǎn)換成結(jié)構(gòu)體之后,有一個(gè)void *__isa
指針的成員變量娩脾,這說(shuō)明我們也可以把它看作實(shí)例赵誓。