美文网首页
iOS - block - 捕获对象类型

iOS - block - 捕获对象类型

作者: felix6 | 来源:发表于2019-04-12 17:53 被阅读0次

    [toc]

    参考

    block - 捕获对象类型

    捕获全局/静态对象类型 <TBC?>

    OC代码

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSObject *obj = [[NSObject alloc] init];
            NSLog(@"1_obj = %@ - %p", obj, &obj);
    
            void (^block)(void) = ^{
                NSLog(@"2_obj = %@ - %p", obj, &obj);
            };
            NSLog(@"3_obj = %@ - %p", obj, &obj);
    
            block();
            NSLog(@"4_obj = %@ - %p", obj, &obj);
        }
        return 0;
    }
    
    MRC 输出: 
    1_obj = <NSObject: 0x103801d20> - 0x7ffeefbff408
    3_obj = <NSObject: 0x103801d20> - 0x7ffeefbff408
    2_obj = <NSObject: 0x103801d20> - 0x7ffeefbff3f8 // 捕获了obj瞬时值, 所以是不同的地址, 但也和block一样, 都在栈上 
    4_obj = <NSObject: 0x103801d20> - 0x7ffeefbff408
    
    ARC 输出: 
    1_obj = <NSObject: 0x103007670> - 0x7ffeefbff408
    3_obj = <NSObject: 0x103007670> - 0x7ffeefbff408
    2_obj = <NSObject: 0x103007670> - 0x100503e90 // 指针随block拷贝到堆
    4_obj = <NSObject: 0x103007670> - 0x7ffeefbff408
    

    C++代码

    MRC/ARC下, 编译的C++代码一致:

    int main(int argc, const char * argv[]) {
        { __AtAutoreleasePool __autoreleasepool;  /* @autoreleasepool */
            NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_9da835_mi_0, obj, &obj);
    
            void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, obj, 570425344));
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_9da835_mi_2, obj, &obj);
    
            ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_9da835_mi_3, obj, &obj);
        }
        return 0;
    }
    
    
    struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0* Desc;
        NSObject *__strong obj; // 捕获
        // 第3个入参
        __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSObject *__strong _obj, int flags=0) : obj(_obj) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    };
    
    
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
        // 从block结构中获取捕获的变量
        NSObject *__strong obj = __cself->obj; // bound by copy 
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_9da835_mi_1, obj, &obj);
    }
    
    
    // block捕获了对象类型的局部变量, desc 增加了 copy 和 dispose 两个函数 (与对象是否可变无关)★
    static struct __main_block_desc_0 {
      size_t reserved;
      size_t 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};
    
    
    static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {
        _Block_object_assign((void*)&dst->obj, (void*)src->obj, 3/*BLOCK_FIELD_IS_OBJECT*/);
    }
    
    
    static void __main_block_dispose_0(struct __main_block_impl_0*src) {
        _Block_object_dispose((void*)src->obj, 3/*BLOCK_FIELD_IS_OBJECT*/);
    }
    

    捕获对象类型的局部变量, 会增加 copy 和 dispose 函数

    相关文章

      网友评论

          本文标题:iOS - block - 捕获对象类型

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