美文网首页
Objective-C的Block实质与实现探究 part-5

Objective-C的Block实质与实现探究 part-5

作者: KardelShaw | 来源:发表于2017-01-04 01:19 被阅读0次

    Block截获对象的情况

    </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]);
    

    输出结果:

    array count = 1
    array count = 2
    array count = 3
    

    代码分析:在Block语法中使用array变量,因此array会被在栈上的Block所截获,接着Block执行了copy方法,Block和array被同时复制到堆上。所以我们才能够在array超出作用域范围而继续使用它,此时使用的是被复制到堆上的array

    转换成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截获对象和使用__block变量时的C++代码十分相似。
    array被Block截获后,变成了Block结构体中的id __strong array成员变量。但是Objective-C中,C语言结构体不能含有__strong修饰符的变量。因为编译器不知道应何时进行C语言结构体的初始化和废弃操作,不能很好地管理内存。但是Objective-C的运行时库却能够做到,所以即使Block结构体中有__strong修饰符的变量也可以恰当初始化和废弃。

    </br>

    对比__block变量和截获对象两种情况的copy和dispose函数差异如下:


    《Objective-C高级编程 iOS与OS X多线程和内存管理 》表2-7

    截获对象也算是截获自动变量的一种,为什么截获自动变量时,不需要copy和dispose函数呢?
    其实也是有的,只不过没有显示出来。
    </br>

    相关文章

      网友评论

          本文标题:Objective-C的Block实质与实现探究 part-5

          本文链接:https://www.haomeiwen.com/subject/ghqovttx.html