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]);
// 结果打印:
array count = 1
array count = 2
array count = 3
struct __block_impl {
void * isa;
int Flags;
int Reserved;
void *FuncPtr;
};
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_imp1_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;
};
// 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]);
C语言结构体中不能含有附有 __strong 修饰符的变量。
因为编译器不知道应何时进行C语言结构体的初始化和废弃操作,不能很好的管理内存。
但是Objective—C 的运行时库能偶准确把握Block 从栈复制到堆 以及堆上的Block被废弃的时机。
什么时候栈上的Block 会复制到堆呢?
① 调用Block 的copy 实例方法时;
② 将Block 作为函数返回值返回时;
③ 将Block 赋值给附有 __strong 修饰符id类型的类或者Block 类型成员变量时;
④ 在方法名中含有 usingBlock 的Cocoa 框架方法 或者 Grand Central Dispatch 的API中传递Block时。
如果使用 __weak修饰符会如何:
blk_t blk;
{
id array = [[NSMutableArray alloc] init];
id __weak array2 = array;
blk = [^(id obj){
[array2 addObject:obj];
NSLog(@“array count = %ld”, [array2 count]];
} copy];
}
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
// 结果打印:
array2 count = 0
array2 count = 0
array2 count = 0
由于附有 __strong 修饰符的变量array在该变量作用域结束时被释放,废弃。nil被赋值到__weak 修饰的array2中。
若 __weak 和 __block 同时使用:
blk_t blk;
{
id array = [[NSMutableArray alloc] init];
__block id __weak array2 = array;
blk = [^(id obj){
[array2 addObject:obj];
NSLog(@“array count = %ld”, [array2 count]];
} copy];
}
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
blk([[NSObject alloc] init]);
// 结果打印:
array2 count = 0
array2 count = 0
array2 count = 0
即使附有 __block 说明符,附有__strong 修饰符的变量array 也会在该变量的作用域结束的时候被释放废弃,nil被赋值给附有 __weak 修饰符的变量array2中。