首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Blocks笔记(4)

Blocks笔记(4)

堆上的block
    上述代码若是把数组中的block copy到堆上,即把getBlockArrayFromStack替换为下面方法,那么注释代码打开与否都无影响,原因在于copy到堆上后block仍能脱离作用域继续存在,并指向堆上的block;

    -(NSArray *)getBlockArrayFromHeap {
        NSArray *blockArray = [[NSArray alloc]initWithObjects:[^{NSLog(@"block-1");} copy],
                               [^{NSLog(@"block-2");} copy],
                               [^{NSLog(@"block-3");} copy],nil];
        return blockArray;
    }

__block变量

__block 说明符可以修饰任何类型的自动变量, __block修饰的变量其实也是block是一种结构体,初始化结构体的时候会把变量赋值给结构体的同名成员变量,若是变量是对象则会持有它,访问变量的时候则通过它的成员变量__forwarding来访问,结构如下:

    struct __Block_byref_obj_0
    {
        void *__isa;
        __Block_byref_obj_0 *__forwarding;
        int __flags;
        int __size;
        void (*__Block_byref_id_object_copy)(void*, void*);
        void (*__Block_byref_id_object_dispose)(void*);
        __strong id obj;
    };
     
    static void __Block_byref_id_object_copy_131(void *dst, void *src)
    {
        _Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
    }
     
    static void __Block_byref_id_object_dispose_131(void *src)
    {
        _Block_object_dispose(*(void * *) ((char*)src + 40), 131);
    }
     
    /* __block variable declaration */
     
    __Block_byref_obj_0 obj = { 0,
                                &obj,
                                0x2000000,
                                sizeof(__Block_byref_obj_0),
                                __Block_byref_id_object_copy_131,
                                __Block_byref_id_object_dispose_131,
                                [[NSObject alloc] init]
                               };

    当block从栈copy到堆时,__block变量也会一同拷贝到堆上并被该block持有;若干个block引用同一个 __block变量,会增加该block的引用计数,当block废弃时,_block会被释放,若它引用计数为0了就会被废弃,同oc的引用计数内存管理完全一样;

    无论是在block语法中,block语法外使用__block变量,还是__block变量配置在栈上或堆上,都可以顺利访问到同一个__block变量,访问形式均可转换为: ++(val.__forwarding->val),原因是: 栈上的__block用结构体实例在__block变量复制到堆上,都会将结构体(__block)的成员变量__forwarding的值替换为复制到堆上__block变量用结构体实例的地址,具体见下面例子:

     - (IBAction)test_1id)sender {
        __block int val = 0;
        void (^block)(void) = [^{val++;} copy];
        val++;
        block();
        NSLog(@"%d",val);
    }
    打印结果: 2
---------------------
返回列表