block的内存管理
block截获对象
typedef void (^myBlock)(id obj);
myBlock block;
- (IBAction)test_6id)sender {
[self captureObject];
block([[NSObject alloc]init]);
block([[NSObject alloc]init]);
block([[NSObject alloc]init]);
}
//截获对象
- (void)captureObject {
id array = [[NSMutableArray alloc] init];
block = [^(id obj){
[array addObjectbj];
NSLog(@"array count = %ld", [array count]);
} copy];
}
翻译代码:
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 addObjectbj];
NSLog(@"array count = %ld", [array count]);
}
static void __main_block_copy_0(struct __main_block_impl_0 *dst, __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);
}
struct 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
};
/* Block literal and executing the Block */
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的内存管理:
1.栈上的block copy到堆上时,通过copy方法,__main_block_copy_0函数使用_Block_object_assign函数将变量array对象赋值给block结构体成员变量并持有该对象; _Block_object_assign调用相当于retain实例方法的函数,而__main_block_dispose_0函数使用_Block_object_dispose函数释放赋值在结构体成员变量array中的对象;
以下情形,block会从栈copy到堆:
.当 block 调用 copy 方法时,如果 block 在栈上,会被拷贝到堆上;
2).当 block 作为函数返回值返回时,编译器自动将 block 作为 _Block_copy 函数,效果等同于 block 直接调用 copy 方法;
3).当 block 被赋值给 __strong id 类型的对象或 block 的成员变量时,编译器自动将 block 作为 _Block_copy 函数,效果等同于 block 直接调用 copy 方法(block用copy修饰的原因);
4).当 block 作为参数被传入方法名带有 usingBlock 的 Cocoa Framework 方法或 GCD 的 API 时。这些方法会在内部对传递进来的 block 调用 copy 或 _Block_copy 进行拷贝;
2.栈区的block(_NSConcreteStackBlock)在作用域结束后就会被废弃;
3.全局的block(_NSConcreteGlobalBlock)的实例是在数据区域,全局都能访问到,不依赖执行时的状态,因此retain、copy、release操作都无效; |