oc block

作者: GTMYang | 来源:发表于2018-05-25 13:53 被阅读0次

    存放方式

    局部block存放在栈区
    block在执行copy操作后存放到堆区,像对象一样开始使用引用计数
    全局block存放在全局区(代码段)

    block与delegate的优劣比较

    delegate 方式处理多回调会更方便一点
    block方式业务代码更紧凑

    block捕获变量

    OC源码

    - (void)initBlock {
        __block OBJ *obj = [OBJ new];
        NSString *bb = @"你好,bb!";
        __block int cc = 33;
        int dd = 55;
        
       // __weak typeof(self) weakSelf = self;
        //void(^temp)(NSString *bb) =
        ^(NSString *bbs) {
           // bb = @"切,什么鬼";
            NSLog(@"%@----> %@   dd=%d", bb, obj, dd);
            cc = 55;
            self.name = @"123";
        };
        //_block = temp;
    }
    

    __block修饰的局部变量会被包装成结构体

    // __block int cc 被包装成下面的结构体
    struct __Block_byref_cc_0 {
      void *__isa;
    __Block_byref_cc_0 *__forwarding;
     int __flags;
     int __size;
     int cc;
    };
    // __block OBJ *obj被包装成下面的结构体
    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*);
     OBJ *obj;
    };
    

    block对应的编译器生成的结构体

    struct __TestBlock__initBlock_block_impl_0 {
      struct __block_impl impl;
      struct __TestBlock__initBlock_block_desc_0* Desc;
      NSString *bb;
      int dd;
      TestBlock *self;  // 捕获self
      __Block_byref_obj_0 *obj; // by ref  // 捕获 __block OBJ *obj 
      __Block_byref_cc_1 *cc; // by ref  // 捕获 __block int cc
    
    /// 构造函数
      __TestBlock__initBlock_block_impl_0(void *fp, struct __TestBlock__initBlock_block_desc_0 *desc, NSString *_bb, int _dd, TestBlock *_self, __Block_byref_obj_0 *_obj, __Block_byref_cc_1 *_cc, int flags=0) : bb(_bb), dd(_dd), self(_self), obj(_obj->__forwarding), cc(_cc->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    block 编译后对应的c函数

    /// block 对应的c函数
    static void __TestBlock__initBlock_block_func_0(struct __TestBlock__initBlock_block_impl_0 *__cself, NSString *bbs) {
      __Block_byref_obj_0 *obj = __cself->obj; // bound by ref
      __Block_byref_cc_1 *cc = __cself->cc; // bound by ref
      NSString *bb = __cself->bb; // bound by copy
      int dd = __cself->dd; // bound by copy
      TestBlock *self = __cself->self; // bound by copy
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_kb_hrh7kmq16p729gwbvk_9qfv80000gn_T_TestBlock_391643_mi_1, bb, (obj->__forwarding->obj), dd);
            (cc->__forwarding->cc) = 55;
            ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)self, sel_registerName("setName:"), (NSString *)&__NSConstantStringImpl__var_folders_kb_hrh7kmq16p729gwbvk_9qfv80000gn_T_TestBlock_391643_mi_2);
        }
    

    block中避免保留环

    // 弱引用方式
    __weak typeof(self) weakSelf = self
    // 或者self对象作为block的参数
    

    __forwarding 的作用

    当block从栈拷贝到堆后,捕获对象变成两份,栈上一份,堆上一份。为了保证捕获对象的一致性,两处的__forwarding都指向堆上的捕获对象,而所有对捕获对象堆操作的操作都改成对__forwarding的操作。

    相关文章

      网友评论

          本文标题:oc block

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