【Objective-C高级编程】iOS与OS X多线程和内存管理(八) __block 从栈上复制到堆 截获对象 数组

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中。




你可能感兴趣的:(读书笔记)