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

iOS - block - 捕获 __block对象类型

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

    [toc]

    参考

    block - 捕获 __block对象类型

    OC代码

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            __block NSObject *obj = [[NSObject alloc] init];
            NSLog(@"1_obj = %@ - %p", obj, &obj);
    
            void (^block)(void) = ^{
                obj = [[NSObject alloc] init];
                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: 0x10283a9c0> - 0x7ffeefbff408 //  __block变量指针始终在栈上
    3_obj = <NSObject: 0x10283a9c0> - 0x7ffeefbff408 
    2_obj = <NSObject: 0x102838eb0> - 0x7ffeefbff408
    4_obj = <NSObject: 0x102838eb0> - 0x7ffeefbff408
    
    ARC 输出:
    1_obj = <NSObject: 0x103a06f40> - 0x7ffeefbff408 // 变量定义时,__block变量指针在栈上
    3_obj = <NSObject: 0x103a06f40> - 0x103a055a8 // 在block定义后, __block变量指针变为堆地址
    2_obj = <NSObject: 0x103a05500> - 0x103a055a8
    4_obj = <NSObject: 0x103a05500> - 0x103a055a8
    

    C++代码

    MRC/ARC 编译后代码一致:

    int main(int argc, const char * argv[]) {
        { __AtAutoreleasePool __autoreleasepool; 
                // __block对象类型变量  __Block_byref_obj_0 obj
            __attribute__((__blocks__(byref))) __Block_byref_obj_0 obj = {(void*)0,(__Block_byref_obj_0 *)&obj, 33554432, sizeof(__Block_byref_obj_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((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_2b7f28_mi_0, (obj.__forwarding->obj), &(obj.__forwarding->obj));
                    
                // 定义block, 捕获的是结构体 val 的地址, 作为第3个入参
            void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_obj_0 *)&obj, 570425344));
         
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_2b7f28_mi_2, (obj.__forwarding->obj), &(obj.__forwarding->obj));
         
            // 调用block
            ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
         
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_p5_mp3284bs2xb073r91w__n99r0000gn_T_main_2b7f28_mi_3, (obj.__forwarding->obj), &(obj.__forwarding->obj));
        }
        return 0;
    }
    
    // __block NSObjcet *obj = [[NSObjcet alloc] init]; 
    // 对象类型的 __block 变量被编译器包装后的结构体
    struct __Block_byref_obj_0 {
        void *__isa; // 
        __Block_byref_obj_0 *__forwarding;
        int __flags;
        int __size;
        void (*__Block_byref_id_object_copy)(void*, void*);  // 对象类型比基本类型多这2个成员 ★
        void (*__Block_byref_id_object_dispose)(void*); // ★
        NSObject *__strong obj; // 结构体内部保存的原始变量
    };
    
    
    struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0* Desc;
        __Block_byref_obj_0 *obj; // by ref
        __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_obj_0 *_obj, int flags=0) : obj(_obj->__forwarding) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    };
    
    // block要执行的代码
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
        __Block_byref_obj_0 *obj = __cself->obj; // bound by ref
        (obj->__forwarding->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_2b7f28_mi_1, (obj->__forwarding->obj), &(obj->__forwarding->obj));
    }
    
    
    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, 8/*BLOCK_FIELD_IS_BYREF*/);
    }
    
    static void __main_block_dispose_0(struct __main_block_impl_0*src) {
        _Block_object_dispose((void*)src->obj, 8/*BLOCK_FIELD_IS_BYREF*/);
    }
    
    

    相关文章

      网友评论

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

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