Block截獲對(duì)象的情況
</br>
typedef void (^blk_t)(id);
blk_t blk;
{
id array = [[NSMutableArray alloc] init];
blk = [^(id obj) {
[array addObject: obj];
NSlog(@"array count = %ld", [array count]);
} copy];
}
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
輸出結(jié)果:
array count = 1
array count = 2
array count = 3
代碼分析:在Block語(yǔ)法中使用array
變量鳞贷,因此array
會(huì)被在棧上的Block所截獲疆偿,接著Block執(zhí)行了copy方法,Block和array
被同時(shí)復(fù)制到堆上搓幌。所以我們才能夠在array
超出作用域范圍而繼續(xù)使用它杆故,此時(shí)使用的是被復(fù)制到堆上的array
。
轉(zhuǎn)換成C++代碼:
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0 *Desc;
id __strong array;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, id __strong _array, int flags=0) : array(_array) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
}
static void __main_block_func_0(struct __main_block_impl_0 *cself, id obj) {
id __strong array = __cself->array;
[array addObject: obj];
NSLog(@"array count = %ld", [array count]);
}
static void __main_block_copy_0(struct __main_block_impl_0 *dst, struct __main_block_impl_0 *src) {
_Block_object_assign(&dst->array, src->array, BLOCK_FIELD_IS_OBJECT);
}
static void __main_block_dispose_0(struct __main_block_impl_0 *src) {
_Block_object_dispose(src->array, BLOCK_FIELD_IS_OBJECT);
}
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
};
blk_t blk;
{
id __strong array = [[NSMutableArray alloc] init];
blk = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, array, 0x22000000);
blk = [blk copy];
}
(*blk->impl.FuncPtr)(blk, [[NSObject alloc] init]);
(*blk->impl.FuncPtr)(blk, [[NSObject alloc] init]);
(*blk->impl.FuncPtr)(blk, [[NSObject alloc] init]);
可以看出溉愁,Block截獲對(duì)象和使用__block變量時(shí)的C++代碼十分相似处铛。
array
被Block截獲后,變成了Block結(jié)構(gòu)體中的id __strong array
成員變量拐揭。但是Objective-C中撤蟆,C語(yǔ)言結(jié)構(gòu)體不能含有__strong
修飾符的變量。因?yàn)榫幾g器不知道應(yīng)何時(shí)進(jìn)行C語(yǔ)言結(jié)構(gòu)體的初始化和廢棄操作堂污,不能很好地管理內(nèi)存家肯。但是Objective-C的運(yùn)行時(shí)庫(kù)卻能夠做到,所以即使Block結(jié)構(gòu)體中有__strong
修飾符的變量也可以恰當(dāng)初始化和廢棄盟猖。
</br>
對(duì)比__block變量和截獲對(duì)象兩種情況的copy和dispose函數(shù)差異如下:
《Objective-C高級(jí)編程 iOS與OS X多線程和內(nèi)存管理 》表2-7
截獲對(duì)象也算是截獲自動(dòng)變量的一種讨衣,為什么截獲自動(dòng)變量時(shí),不需要copy和dispose函數(shù)呢式镐?
其實(shí)也是有的反镇,只不過(guò)沒(méi)有顯示出來(lái)。
</br>