美文网首页
OC:深入探究 block

OC:深入探究 block

作者: LiYaoPeng | 来源:发表于2020-02-05 16:16 被阅读0次

    主要分析了block在持有__block、__weak、__strong修饰的对象时,block结构发生的变化。

    以及block对持有变量的引用计数造成的具体影响。

    思考:

    @implementation TestCode
    - (void)testFunc {
        @weakify(self)
        self.block111 = ^{
            @strongify(self);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self) {
                    printf("\n\nstrongPerson1 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
                }else{
                    printf("self Retain Count = 0 \n");
                }
            });
        };
    }
    
    - (void)dealloc {
        printf("\n");
        printf("✅ 【dealloc】 Retain Count = 0");
    }
    @end
    
      
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        TestCode *t = [[TestCode alloc]init];
        [t testFunc];
        
        if (t.block111) {
            t.block111();
        }
    }
    @end
    

    注意: 以下block111是self所持有的block

    • 如果在block111 中对 NSMutableArray *arrayM 进行增删元素, arrayM是否需要用__block修饰?

    • block111 中对weakSelf进行 __strong typeof(weakSelf) strongSelf = weakSelf 修饰

      • 如果block一直不调用,那么self是否可以正常销毁?
      • 当运行到__strong typeof(weakSelf) strongSelf = weakSelf的下一行时,self引用计数最少是多少?

    一:基本介绍

    定义

    Block 是带有自动变量(局部变量)的匿名函数, 是 C 语言的扩充功能,其本质是一个OC对象。

    1. 作为属性

      @property (nonatomic,copy) void(^block)(void);

    2. 作为参数

      - (void) getDataWithBlock:(id(^)(id parameter))block;

    3. 作为返回值(masonry)

      - (MASConstraint * (^)(id))equalTo

    结构

    - (void)testFunc {
        self.block111 = ^{
            printf("block测试代码");
        };
        self.block111();
    }
    

    OC代码转成c++代码

    clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -fobjc-arc -fobjc-runtime=macosx-10.13 xxxxxx.m

    static void _I_TestCode_testFunc(TestCode * self, SEL _cmd) {
        /// self.block = &__TestCode__testFunc_block_impl_0(A,B)
        ((void (*)(id, SEL, void (^ _Nonnull)()))(void *)objc_msgSend)
         ((id)self, sel_registerName("setBlock111:"),
          (
           (void (*)())&__TestCode__testFunc_block_impl_0
            (
             (void *)__TestCode__testFunc_block_func_0,// 参数1
             &__TestCode__testFunc_block_desc_0_DATA// 参数2__TestCode__testFunc_block_desc_0,
            )
           )
         );
        
        ((void (*(*)(id, SEL))())(void *)objc_msgSend)((id)self, sel_registerName("block111"))();
    }
    

    上段代码的基本意思是

    1. self.block = &__TestCode__testFunc_block_impl_0(A,B)

      1. A: __TestCode__testFunc_block_func_0
      2. B: __TestCode__testFunc_block_desc_0_DATA

    1. __TestCode__testFunc_block_impl_0

    struct __TestCode__testFunc_block_impl_0 {
      
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
      
      __TestCode__testFunc_block_impl_0(void *fp, struct __TestCode__testFunc_block_desc_0 *desc, int flags=0) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    命名规律:_类名_方法名_block_impl_层级

    上述代码中可以看出block 被编译成了__TestCode__testFunc_block_impl_0结构体

    1. 其内部有一个同名的构造函数__TestCode__testFunc_block_impl_0
    2. 两个属性
      1. __block_impl impl

      2. __TestCode__testFunc_block_desc_0* Desc

    2. __block_impl

    struct __block_impl {
      void *isa;// 指向了&_NSConcreteStackBlock
      int Flags;
      int Reserved;
      void *FuncPtr; // 用于方法的储存本质是一个 __TestCode__testFunc_block_func_0 c函数
    };
    

    可以发现__block_impl结构体内部就有一个isa指针。因此可以证明block本质上就是一个oc对象。

    __block_impl结构体中isa指针存储着&_NSConcreteStackBlock地址,可以暂时理解为其类对象地址,block就是_NSConcreteStackBlock类型的。

    1. 看到isa就会联想到之前在objc_class结构体,因此我们的block本质上也是一个对象【而且是个类对象】
      我们知道实例对象->类对象->元类构成了isa链中的一条,而这个__block_impl结构体占据的是中间类对象的位置
    2. 这里的isa指针会指向元类,这里的元类主要是为了说明这个块的存储区域

    __TestCode__testFunc_block_func_0

    static void __TestCode__testFunc_block_func_0(struct __TestCode__testFunc_block_impl_0 *__cself) {
            printf("block测试代码");
    }
    

    __TestCode__testFunc_block_func_0 中存放的是block中的代码

    3. __TestCode__testFunc_block_desc_0

    static struct __TestCode__testFunc_block_desc_0 {
      size_t reserved;
      size_t Block_size;
    } __TestCode__testFunc_block_desc_0_DATA = { 0, sizeof(struct __TestCode__testFunc_block_impl_0)};
    

    主要是存储了block的大小

    4. 同名的构造函数__TestCode__testFunc_block_impl_0(void *fp, struct __TestCode__testFunc_block_desc_0 *desc, int flags=0)

    __TestCode__testFunc_block_impl_0
        (void *fp, struct __TestCode__testFunc_block_desc_0 *desc, int flags=0)
        {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    

    同名函数主要对两个属性进行了赋值

    • void *fp 就是 (void *)__TestCode__testFunc_block_func_0__
    • __ struct __TestCode__testFunc_block_desc_0 *desc 就是 &__TestCode__testFunc_block_desc_0_DATA

    5. 结构图

    image

    二:持有变量时block的结构

    以上分析的是 block 不持有任何外部变量,但是当block持有外部变量的时候,就会额外生成一些东西。

    持有基本数据类型

    持有的基本数据类型分为是否用__block修饰,如下,a__block修饰,b没有。

    - (void)testFunc {
        __block NSInteger a = 0;
        NSInteger b = 0;
        self.block111 = ^{
            a = 12 + b;
            printf("block测试代码");
        };
        self.block111();
    }
    

    思考

    a__block修饰后可以修改,必然a从值传递,变成了地址传递。

    1. __bloka封装成了什么结构?
    2. 结构a的值到底存在哪里?
    3. 结构a是怎么管理内存的?

    要回答上述问题,我们需要查看- (void)testFunc{}编译的源码:

    编译后:

    static void _I_TestCode_testFunc(TestCode * self, SEL _cmd) {
        // 结构体 a 的生成  (__block NSInteger a = 0;)
        __attribute__((__blocks__(byref))) __Block_byref_a_0 a =
        {
            (void*)0, // isa
            (__Block_byref_a_0 *)&a,// a地址的传递
            0,// flags
            sizeof(__Block_byref_a_0),// size
            0// a的值
        };
        
        NSInteger b = 0;
        
        ((void (*)(id, SEL, void (^ _Nonnull)()))(void *)objc_msgSend)
        ((id)self, sel_registerName("setBlock111:"),
         
         /// 初始化__TestCode__testFunc_block_impl_0结构体
         ((void (*)())&__TestCode__testFunc_block_impl_0
          (
           (void *)__TestCode__testFunc_block_func_0,
           &__TestCode__testFunc_block_desc_0_DATA,
           
           b,//值传递b
           (__Block_byref_a_0 *)&a,//把结构体(对象)a的地址传了进去
           
           570425344
           ))
         );
        
        ((void (*(*)(id, SEL))())(void *)objc_msgSend)((id)self, sel_registerName("block111"))();
    }
    

    1. __Block_byref_a_0

    struct __Block_byref_a_0 {
      void *__isa;
    __Block_byref_a_0 *__forwarding;
     int __flags;
     int __size;
     NSInteger a;
    };
    
    // 结构体 a 的生成 
        __attribute__((__blocks__(byref))) __Block_byref_a_0 a =
        {
            (void*)0, // isa
            (__Block_byref_a_0 *)&a,// a地址的传递
            0,// flags
            sizeof(__Block_byref_a_0),// size
            0// a的值
        };
    
    • 用了__block修饰的a,生成了一个用__attribute__ 修饰的 __Block_byref_a_0类型的结构体。
    • 结构体内部有一个isa指针,说明__Block_byref_a_0其本质也是一个OC对象

    2. __TestCode__testFunc_block_impl_0结构体

    struct __TestCode__testFunc_block_impl_0 {
        
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
        
      NSInteger b;
      __Block_byref_a_0 *a; // by ref
        
      // 同名的构造函数
      __TestCode__testFunc_block_impl_0
        (
         
         void *fp,
         struct __TestCode__testFunc_block_desc_0 *desc,
         NSInteger _b,
         __Block_byref_a_0 *_a,
         int flags=0
         
         ) : b(_b), a(_a->__forwarding) { ... }
    };
    

    生成了新的属性:

    • NSInteger b

      • _b就是栈区的b
      • b 值传递
    • __Block_byref_a_0 *a

      • 由于赋值到__TestCode__testFunc_block_impl_0时,传递的是 栈区的__Block_byref_a_0 a的地址,所以 _a == &a

      • 因为_a->__forwarding就是&_a因此__TestCode__testFunc_block_impl_0结构体中的a指向的就是栈中的a

    小结论:

    1. block中的b和外部的b,只是值传递,因此即便外部修改了b的值,也不会对blockb产生影响。
    2. __block a;a包装成了一个结构体,而block内部属性__Block_byref_a_0 *a就是栈区结构体a的地址
    3. 此时, block没有copy操作,所以block存在栈区,结构体a也存在栈区

    3. __TestCode__testFunc_block_desc_0

    
    static struct __TestCode__testFunc_block_desc_0 {
      size_t reserved;
      size_t Block_size;
       //copy 函数
      void (*copy)(
        struct __TestCode__testFunc_block_impl_0*, 
        struct __TestCode__testFunc_block_impl_0*
      );
      // dispose 函数
      void (*dispose)(struct __TestCode__testFunc_block_impl_0*);
        
    } __TestCode__testFunc_block_desc_0_DATA = 
                                                                        { 0,// reserved
                                       sizeof(struct __TestCode__testFunc_block_impl_0), //size
                                       __TestCode__testFunc_block_copy_0,//copy
                                       __TestCode__testFunc_block_dispose_0//dispose
                                       };
    

    生成了 copy dispose 函数

    a. __TestCode__testFunc_block_copy_0
    1. block被拷贝到堆区的时候调用

    2. 实现函数是 _Block_object_assign,它根据对象的 flags 来判断是否需要拷贝,或者只是赋值。

    // copy
    static void __TestCode__testFunc_block_copy_0(struct __TestCode__testFunc_block_impl_0*dst, struct __TestCode__testFunc_block_impl_0*src){
      _Block_object_assign(
                            (void*)&dst->a, 
                (void*)src->a,
                8/*BLOCK_FIELD_IS_BYREF*/
                            );
    }
    
    _Block_object_assign

    函数实现在 runtime.c

    /**
    _Block_object_assign参数flag相关
                    // 是一个对象
            BLOCK_FIELD_IS_OBJECT   =  3, 
            // 是一个block
            BLOCK_FIELD_IS_BLOCK    =  7, 
            // 被__block修饰的变量
            BLOCK_FIELD_IS_BYREF    =  8,  
            // 被__weak修饰的变量,只能被辅助copy函数使用 
            BLOCK_FIELD_IS_WEAK     = 16,  
            // block辅助函数调用(告诉内部实现不要进行retain或者copy)
            BLOCK_BYREF_CALLER      = 128 
    **/
    
    void _Block_object_assign(void *destAddr, const void *object, const int flags) {
      
      // BLOCK_BYREF_CALLER block辅助函数调用(告诉内部实现不要进行retain或者copy)
        if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) {
          
          //BLOCK_FIELD_IS_WEAK 被__weak修饰的变量,只能被辅助copy函数使用 
            if ((flags & BLOCK_FIELD_IS_WEAK) == BLOCK_FIELD_IS_WEAK) {
                _Block_assign_weak(object, destAddr);
            }
            else {
                _Block_assign((void *)object, destAddr);
            }
        }
      
      // 被__block修饰的变量
        else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF)  {
          ///最终走到这边 
            _Block_byref_assign_copy(destAddr, object, flags);
        }
      
      // 是一个block
        else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) {
            _Block_assign(_Block_copy_internal(object, flags), destAddr);
        }
      
      // 是一个对象
        else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) {
            _Block_retain_object(object);
            _Block_assign((void *)object, destAddr);
        }
    }
    
    /*
    Block_private.h
    https://opensource.apple.com/source/libclosure/libclosure-73/Block_private.h
    */
     enum {
            BLOCK_DEALLOCATING =      (0x0001),  // runtime
            BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
            BLOCK_NEEDS_FREE =        (1 << 24), // runtime
            BLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
            BLOCK_HAS_CTOR =          (1 << 26), // compiler: helpers have C++ code
            BLOCK_IS_GC =             (1 << 27), // runtime
            BLOCK_IS_GLOBAL =         (1 << 28), // compiler
            BLOCK_USE_STRET =         (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
            BLOCK_HAS_SIGNATURE  =    (1 << 30), // compiler
            BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31)  // compiler
        };
    
    struct Block_byref {
        void *isa;
        struct Block_byref *forwarding;
        int flags; /* refcount; */
        int size;
    };
    
    
    /** runtime.c
    http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/BlocksRuntime/runtime.c
    */
    static void *_Block_copy_class = _NSConcreteMallocBlock;
    static void *_Block_copy_finalizing_class = _NSConcreteMallocBlock;
    static int _Block_copy_flag = BLOCK_NEEDS_FREE;
    static int _Byref_flag_initial_value = BLOCK_NEEDS_FREE | 2;
    
    static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
    
        struct Block_byref **destp = (struct Block_byref **)dest;
        struct Block_byref *src = (struct Block_byref *)arg;
    
            //不需要做任何操作
        if (src->forwarding->flags & BLOCK_IS_GC) {
        }
      
            // 需要copy到堆区 并且需要操作引用计数
        else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
            // src points to stack
            bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK));
            // if its weak ask for an object (only matters under GC)
            struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
            copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack
            copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier)
            src->forwarding = copy;  // patch stack to point to heap copy
            copy->size = src->size;
            if (isWeak) {
                copy->isa = &_NSConcreteWeakBlockVariable;  // mark isa field so it gets weak scanning
            }
            if (src->flags & BLOCK_HAS_COPY_DISPOSE) {
                // Trust copy helper to copy everything of interest
                // If more than one field shows up in a byref block this is wrong XXX
                copy->byref_keep = src->byref_keep;
                copy->byref_destroy = src->byref_destroy;
                (*src->byref_keep)(copy, src);
            }
            else {
                // just bits.  Blast 'em using _Block_memmove in case they're __strong
                _Block_memmove(
                    (void *)&copy->byref_keep,
                    (void *)&src->byref_keep,
                    src->size - sizeof(struct Block_byref_header));
            }
        }
        // 已经复制到堆、只操作引用计数
        else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) {
            latching_incr_int(&src->forwarding->flags);
        }
        // assign byref data block pointer into new Block
        // 其实进行了 *destp = src->forwarding 操作,把栈区的a,变成了 Block_byref *copy
        _Block_assign(src->forwarding, (void **)destp);
    }
    
    static void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default;
    
    static void _Block_assign_default(void *value, void **destptr) {
        *destptr = value;
    }
    

    省略后的代码

    
    struct Block_byref {
        void *isa;
        struct Block_byref *forwarding;
        int flags; /* refcount; */
        int size;
    };
    
    static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
        ...
        struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
        copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack
        // 堆中拷贝的forwarding指向它自己
        copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier)
        // 栈中的forwarding指向堆中的新对象
        src->forwarding = copy;  // patch stack to point to heap copy
        copy->size = src->size;
        ...
         // 其实进行了 *destp = src->forwarding 操作,把栈区的a,变成了 Block_byref *copy
        _Block_assign(src->forwarding, (void **)destp);
    }
    

    可以看到,Block_byref__Block_byref_a_0 的前4个成员类型相同,可以互相转化。

    b. __TestCode__testFunc_block_dispose_0
    // dispose
    static void __TestCode__testFunc_block_dispose_0(struct __TestCode__testFunc_block_impl_0*src){
    _Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);
    }
    
    _Block_object_dispose
    void _Block_object_dispose(const void *object, const int flags) {
        //printf("_Block_object_dispose(%p, %x)\n", object, flags);
        if (flags & BLOCK_FIELD_IS_BYREF)  {
          // 释放 __block 修饰的变量
            _Block_byref_release(object);
        }
        else if ((flags & (BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_BLOCK) {
                    // 释放block 引用的 block
            _Block_destroy(object);
        }
        else if ((flags & (BLOCK_FIELD_IS_WEAK|BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_OBJECT) {
            // 释放block 引用的对象
            _Block_release_object(object);
        }
    }
    
    static void _Block_byref_release(const void *arg) {
        struct Block_byref *shared_struct = (struct Block_byref *)arg;
        int refcount;
    
        shared_struct = shared_struct->forwarding;
    
        if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) {
            return; // stack or GC or global
        }
        refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK;
        if (refcount <= 0) {
            printf("_Block_byref_release: Block byref data structure at %p underflowed\n", arg);
        }
        else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) {
            if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) {
                (*shared_struct->byref_destroy)(shared_struct);
            }
            _Block_deallocator((struct Block_layout *)shared_struct);
        }
    }
    
    static void (*_Block_deallocator)(const void *) = (void (*)(const void *))free;
    
    static int latching_decr_int(int *where) {
        while (1) {
            int old_value = *(volatile int *)where;
            if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
                return BLOCK_REFCOUNT_MASK;
            }
            if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
                return 0;
            }
            if (OSAtomicCompareAndSwapInt(old_value, old_value-1, (volatile int *)where)) {
                return old_value-1;
            }
        }
    }
    

    __block修饰的变量,释放时要用 latching_decr_int函数减引用计数,直到计数为0,就释放该对象;

    而普通的对象、block,就直接释放销毁。

    小结:

    1. 生成了copy despose函数。

    2. copy 调用时机:

      1. block进行copy操作的时候就会自动调用__TestCode__testFunc_block_desc_0内部的__TestCode__testFunc_block_copy_0函数,__TestCode__testFunc_block_copy_0函数内部会调用_Block_object_assign函数。
      2. _Block_object_assign内部是根据传递的flags类型来对a进行copyretain操作
    3. despose 调用时机:

      1. block从堆中移除时就会自动调用__TestCode__testFunc_block_desc_0__TestCode__testFunc_block_dispose_0函数,__TestCode__testFunc_block_dispose_0函数内部会调用_Block_object_dispose函数。
      2. _Block_object_dispose会对 a做释放操作,类似于release

    4. __TestCode__testFunc_block_func_0

    __TestCode__testFunc_block_func_0__block_impl结构体中存储的block代码

    static void __TestCode__testFunc_block_func_0(struct __TestCode__testFunc_block_impl_0 *__cself) {
      
      __Block_byref_a_0 *a = __cself->a; // bound by ref
      NSInteger b = __cself->b; // bound by copy
      
      (a->__forwarding->a) = 12 + b;
       printf("block测试代码");
    }
    

    __cself就是我们定义的block

    a->__forwarding其实修改的就是我们堆区的(Block_byref) copy (注意 在ARC下我们的block会自动copy)

    下图在TestCode.m中自定义了结构体:

    struct __Block_byref_a_0 {
        void *__isa;
        struct __Block_byref_a_0 *__forwarding;
        int __flags;
        int __size;
        NSInteger a;
    };
    struct __block_impl {
        void *isa;// 指向了&_NSConcreteStackBlock
        int Flags;
        int Reserved;
        void *FuncPtr; // 用于方法的储存本质是一个 __TestCode__testFunc_block_func_0 c函数
    };
    struct __TestCode__testFunc_block_impl_0 {
        
        struct __block_impl impl;
        struct __TestCode__testFunc_block_desc_0* Desc;
        struct __Block_byref_a_0 *a; // by ref
    };
    
    截屏2020-02-01下午4.30.11.png

    5. 结构图

    __block NSInteger a = 0;
    NSInteger b = 0;
    self.block111 = ^{
        a = 12 + b;
        printf("block测试代码");
    };
    
    image

    持有对象类型

    对象类型的引用分为三种情况:

    1. __block 修饰
    2. __strong 修饰(@strongify)
    3. __weak 修饰 (@weakify)

    ⚠️注意下面的代码产生了循环引用,随后会做详细的分析

    - (void)testFunc {
        
        __weak typeof(self)weakSelf = self;
        __block TestCode *blockSelf = weakSelf;
        
        self.block111 = ^{
            __strong typeof(weakSelf)strongSelf = weakSelf;
            void(^block222)(void) = ^{
                blockSelf = strongSelf;
                printf("\nblock测试代码\n");
            };
            block222();
        };
        
        self.block111();
    }
    

    编译上述代码:

    static void _I_TestCode_testFunc(TestCode * self, SEL _cmd) {
    
        __attribute__((objc_ownership(weak))) typeof(self)weakSelf = self;
        __attribute__((__blocks__(byref))) __Block_byref_blockSelf_0 blockSelf =
        {
            (void*)0,
            (__Block_byref_blockSelf_0 *)&blockSelf,
            33554432,
            sizeof(__Block_byref_blockSelf_0),
            __Block_byref_id_object_copy_131,
            __Block_byref_id_object_dispose_131,
            weakSelf
        };
    
        // 创建 __TestCode__testFunc_block_impl_1
        ((void (*)(id, SEL, void (^ _Nonnull)()))(void *)objc_msgSend)((id)self, sel_registerName("setBlock111:"), ((void (*)())&__TestCode__testFunc_block_impl_1
         (//参数:
          (void *)__TestCode__testFunc_block_func_1,
          &__TestCode__testFunc_block_desc_1_DATA,
          weakSelf,
          (__Block_byref_blockSelf_0 *)&blockSelf,
          570425344)
          ));
    
        ((void (*(*)(id, SEL))())(void *)objc_msgSend)((id)self, sel_registerName("block111"))();
    }
    

    1. __Block_byref_blockSelf_0

    struct __Block_byref_blockSelf_0 {
      //【值为:0】[8个字节]
      void *__isa;
      //【值为&blockSelf】,[8个字节]
    __Block_byref_blockSelf_0 *__forwarding;
      
     int __flags;//【值为33554432】,[4个字节]
     int __size;//【值为sizeof(__Block_byref_blockSelf_0)】,[4个字节]
      
      //【__Block_byref_id_object_copy_131】[8个字节]
     void (*__Block_byref_id_object_copy)(void*, void*);
      //【__Block_byref_id_object_dispose_131】,[8个字节]
     void (*__Block_byref_id_object_dispose)(void*);
      
     TestCode *__strong blockSelf;//【weakSelf】[8个字节]
    };
    /// 共48个字节
    

    self使用__block修饰后,blockPerson 被包装成了一个与__Block_byref_a_0相似的结构体

    只是比__Block_byref_a_0多了两个函数:

    1. __Block_byref_id_object_copy值为__Block_byref_id_object_copy_131
    2. __Block_byref_id_object_dispose值为__Block_byref_id_object_dispose_131

    ⚠️值得注意的是blockSelf用了__strong修饰,因此产生了循环引用!需要改成__block typeof(weakSelf)blockSelf = weakSelf; 下面会有详细解释

    __Block_byref_id_object_copy_131 与 __Block_byref_id_object_dispose_131

    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_object_assign

    dstsrc就是blockSelf__Block_byref_blockSelf_0结构体指针

    __Block_byref_blockSelf_0共48个字节,所以(char*)dst + 40(char)src + 40,找到的就是TestCode *__strong blockSelf

    最后的flags传递的是131 = 3|128 即 : BLOCK_FIELD_IS_OBJECT|BLOCK_FIELD_IS_CALLER

    调用时机:block执行copy操作,后面会详细分析。

    2. __TestCode__testFunc_block_impl_1

    struct __TestCode__testFunc_block_impl_1 {
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_1* Desc;
        
      TestCode *const __weak weakSelf;
      __Block_byref_blockSelf_0 *blockSelf; // by ref
        
      __TestCode__testFunc_block_impl_1(
                                        void *fp,
                                        struct __TestCode__testFunc_block_desc_1 *desc,
                                        TestCode *const __weak _weakSelf,
                                        __Block_byref_blockSelf_0 *_blockSelf,
                                        int flags=0
                                        ) : weakSelf(_weakSelf), blockSelf(_blockSelf->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    
    

    生成了两个成员变量:Person *__weak weakPerson;__Block_byref_blockPerson_0 *blockPerson;

    **a. __block_impl impl **

    结构没有任何变化

    1. flags: 570425344表示BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR,即(1<<25 | 1<<29)
    2. FuncPtr: __TestCode__testFunc_block_func_1

    3. __TestCode__testFunc_block_desc_1

    结构没有任何变化

    desc:结构体__TestCode__testFunc_block_desc_1_DATA

    static struct __TestCode__testFunc_block_desc_1 {
      size_t reserved;
      size_t Block_size;
      void (*copy)(struct __TestCode__testFunc_block_impl_1*, struct __TestCode__testFunc_block_impl_1*);
      void (*dispose)(struct __TestCode__testFunc_block_impl_1*);
    } __TestCode__testFunc_block_desc_1_DATA = {
        0,
        sizeof(struct __TestCode__testFunc_block_impl_1),
        __TestCode__testFunc_block_copy_1,
        __TestCode__testFunc_block_dispose_1
    };
    

    值得注意的是:copy、dispose的实现函数

    // copy 函数
    static void __TestCode__testFunc_block_copy_1(struct __TestCode__testFunc_block_impl_1*dst, struct __TestCode__testFunc_block_impl_1*src)
    {
        _Block_object_assign((void*)&dst->weakSelf, (void*)src->weakSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);
        _Block_object_assign((void*)&dst->blockSelf, (void*)src->blockSelf, 8/*BLOCK_FIELD_IS_BYREF*/);
    }
    
    // dispose 函数
    static void __TestCode__testFunc_block_dispose_1(struct __TestCode__testFunc_block_impl_1*src)
    {
        _Block_object_dispose((void*)src->weakSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);
        _Block_object_dispose((void*)src->blockSelf, 8/*BLOCK_FIELD_IS_BYREF*/);
    }
    
    a. 对weakSelf_Block_object_assign操作
    void _Block_object_assign(void *destAddr, const void *object, const int flags) {
      
      // BLOCK_BYREF_CALLER block辅助函数调用(告诉内部实现不要进行retain或者copy)
        if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) { ... }
      // 被__block修饰的变量
        else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF)  { ... }
      // 是一个block
        else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) { ... }
      
      // 是一个对象
        else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) {
            _Block_retain_object(object);
            _Block_assign((void *)object, destAddr);
        }
    }
    

    即直接对对象进行一个_Block_retain_object操作

    但是发现在ARC下_Block_retain_object函数并没有给对象的引用计数+1。

    static void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default;
    static void _Block_retain_object_default(const void *ptr) {
        if (!ptr) return;
    }
    
    b. 对blockSelf_Block_object_assign操作

    最终会调用到_Block_byref_assign_copy函数

    static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
    
        struct Block_byref **destp = (struct Block_byref **)dest;
        struct Block_byref *src = (struct Block_byref *)arg;
    
            //不需要做任何操作
        if (src->forwarding->flags & BLOCK_IS_GC) {
        }
      
            // 需要copy到堆区 并且需要操作引用计数
        else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
            bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK));
          
            struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
            copy->flags = src->flags | _Byref_flag_initial_value;
            copy->forwarding = copy; 
            src->forwarding = copy;  
            copy->size = src->size;
          
            if (isWeak) {
                copy->isa = &_NSConcreteWeakBlockVariable;  
            }
            if (src->flags & BLOCK_HAS_COPY_DISPOSE) {
              /// 调用 __Block_byref_blockSelf_0 中的 __Block_byref_id_object_copy 函数
                        /// 执行byref的byref_keep函数(即assign函数,只是会加上BLOCK_BYREF_CALLER标志),管理捕获的对象内存
                copy->byref_keep = src->byref_keep;
                copy->byref_destroy = src->byref_destroy;
                (*src->byref_keep)(copy, src);
            }
            else { ... }
        }
        // 已经复制到堆、只操作引用计数
        else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) { ... }
        _Block_assign(src->forwarding, (void **)destp);
    }
    

    值得注意的是在Block_private.h找到了这个结构:

    struct Block_byref {
        void *isa;
        struct Block_byref *forwarding;
        volatile int32_t flags; // contains ref count
        uint32_t size;
    };
    
    struct Block_byref_2 {
        // requires BLOCK_BYREF_HAS_COPY_DISPOSE
        BlockByrefKeepFunction byref_keep;
        BlockByrefDestroyFunction byref_destroy;
    };
    
    struct Block_byref_3 {
        // requires BLOCK_BYREF_LAYOUT_EXTENDED
        const char *layout;
    };
    
    

    其实byref_keep就是blockSelf中的__Block_byref_id_object_copy也就是函数__Block_byref_id_object_copy_131

    所以其调用为

    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_copy_131(__Block_byref_blockSelf_0 *dst, __Block_byref_blockSelf_0 *src) {
     _Block_object_assign(
       dst->blockSelf, 
       *(void * )(src->blockSelf), 
       BLOCK_FIELD_IS_OBJECT|BLOCK_FIELD_IS_CALLER
     );
    }
    

    继续看_Block_object_assign

    void _Block_object_assign(void *destAddr, const void *object, const int flags) {
      
      // BLOCK_BYREF_CALLER block辅助函数调用(告诉内部实现不要进行retain或者copy)
        if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) {
          //BLOCK_FIELD_IS_WEAK 被__weak修饰的变量,只能被辅助copy函数使用 
            if ((flags & BLOCK_FIELD_IS_WEAK) == BLOCK_FIELD_IS_WEAK) {
                _Block_assign_weak(object, destAddr);
            }
            else {
                _Block_assign((void *)object, destAddr);
            }
        }
        else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF)  { ... }
        else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) { ... }
        else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) { ... }
    }
    static void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default;
    
    static void _Block_assign_default(void *value, void **destptr) {
        *destptr = value;
    }
    

    运行了_Block_assign函数,把栈区的__Block_byref_blockSelf_0 blockSelf赋值成了Block_byref copy

    c. 对weakSelfdispose操作
    static void __TestCode__testFunc_block_dispose_1(struct __TestCode__testFunc_block_impl_1*src) 
    {
      _Block_object_dispose(
        (void*)src->self, 
        3/*BLOCK_FIELD_IS_OBJECT*/
      );
      _Block_object_dispose(
        (void*)src->blockSelf,
        8/*BLOCK_FIELD_IS_BYREF*/
      );
    }
    
    void _Block_object_dispose(const void *object, const int flags) {
        if (flags & BLOCK_FIELD_IS_BYREF)  { ... }
        else if ((flags & (BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_BLOCK) {...}
        else if ((flags & (BLOCK_FIELD_IS_WEAK|BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_OBJECT) {
            // 释放block 引用的对象
            _Block_release_object(object);
        }
    }
    static void (*_Block_release_object)(const void *ptr) = _Block_release_object_default;
    static void _Block_release_object_default(const void *ptr) {
        if (!ptr) return;
    }
    

    可以看到:最终会调用到_Block_release_object,内部也是没对引用计数进行操作。

    d. 对blockSelfdispose操作

    其最终走到了_Block_byref_release函数:

    static void _Block_byref_release(const void *arg) {
        struct Block_byref *shared_struct = (struct Block_byref *)arg;
        int refcount;
        shared_struct = shared_struct->forwarding;
        if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) {
            return; 
        }
        refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK;
        if (refcount <= 0) {  }
        else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) {
        /// 主要调用了
            if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) {
                (*shared_struct->byref_destroy)(shared_struct);
            }
            _Block_deallocator((struct Block_layout *)shared_struct);
        }
    }
    
    

    其中__block_release函数内部主要是调用了(*shared_struct->byref_destroy)(shared_struct)

    也就是 __Block_byref_blockSelf_0 *blockSelf 中的__Block_byref_id_object_dispose_131函数

    static void __Block_byref_id_object_dispose_131(void *src) {
         _Block_object_dispose(*(void * *) ((char*)src + 40), 131);
    }
    
    ///译为:
    static void __Block_byref_id_object_dispose_131(__Block_byref_blockSelf_0 *src) {
        
      _Block_object_dispose
       (
         *(void * *) (src->blockSelf), 
         BLOCK_FIELD_IS_OBJECT|BLOCK_FIELD_IS_CALLER
       );
    }
    
    e. __TestCode__testFunc_block_func_1

    查看__TestCode__testFunc_block_func_1,函数中是如何创建第二层block222

    {
      __strong typeof(weakSelf)strongSelf = weakSelf;
            void(^block222)(void) = ^{
                blockSelf = strongSelf;
                printf("\nblock测试代码\n");
            };
            block222();
    }
    
    static void __TestCode__testFunc_block_func_1(struct __TestCode__testFunc_block_impl_1 *__cself) {
        
        __Block_byref_blockSelf_0 *blockSelf = __cself->blockSelf; // bound by ref
        TestCode *const __weak weakSelf = __cself->weakSelf; // bound by copy
    
        ///__strong typeof(weakSelf)strongSelf = weakSelf;
        __attribute__((objc_ownership(strong))) typeof(weakSelf)strongSelf = weakSelf;
        
        /// 创建block222 即:__TestCode__testFunc_block_impl_0结构体
        void(*block222)(void) = ((void (*)())&__TestCode__testFunc_block_impl_0((void *)__TestCode__testFunc_block_func_0,&__TestCode__testFunc_block_desc_0_DATA,strongSelf,(__Block_byref_blockSelf_0 *)blockSelf,570425344));
      
        /// 调用: block222()
        ((void (*)(__block_impl *))((__block_impl *)block222)->FuncPtr)((__block_impl *)block222);
    }
    

    其中block222是一个__TestCode__testFunc_block_impl_0结构体

    4. __TestCode__testFunc_block_impl_0

    struct __TestCode__testFunc_block_impl_0 {
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
        
      TestCode *const __strong strongSelf;
      __Block_byref_blockSelf_0 *blockSelf; // by ref
        
      __TestCode__testFunc_block_impl_0(
                                        void *fp,
                                        struct __TestCode__testFunc_block_desc_0 *desc,
                                        TestCode *const __strong _strongSelf,
                                        __Block_byref_blockSelf_0 *_blockSelf,
                                        int flags=0
                                        ) : strongSelf(_strongSelf), blockSelf(_blockSelf->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    其结构和__TestCode__testFunc_block_impl_1结构相似。

    只不过blockSelf就是上层block(即:block111)中的 blockSelf

    值得注意的是这边有个TestCode *const __strong strongSelf;

    剩下的结构与之前分析的结构大同小异:

    static void __TestCode__testFunc_block_func_0(struct __TestCode__testFunc_block_impl_0 *__cself) {
      __Block_byref_blockSelf_0 *blockSelf = __cself->blockSelf; // bound by ref
      TestCode *const __strong strongSelf = __cself->strongSelf; // bound by copy
    
                (blockSelf->__forwarding->blockSelf) = strongSelf;
                printf("\nblock测试代码\n");
            }
    static void __TestCode__testFunc_block_copy_0(struct __TestCode__testFunc_block_impl_0*dst, struct __TestCode__testFunc_block_impl_0*src) {_Block_object_assign((void*)&dst->blockSelf, (void*)src->blockSelf, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_assign((void*)&dst->strongSelf, (void*)src->strongSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);}
    
    static void __TestCode__testFunc_block_dispose_0(struct __TestCode__testFunc_block_impl_0*src) {_Block_object_dispose((void*)src->blockSelf, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_dispose((void*)src->strongSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);}
    
    static struct __TestCode__testFunc_block_desc_0 {
      size_t reserved;
      size_t Block_size;
      void (*copy)(struct __TestCode__testFunc_block_impl_0*, struct __TestCode__testFunc_block_impl_0*);
      void (*dispose)(struct __TestCode__testFunc_block_impl_0*);
    } __TestCode__testFunc_block_desc_0_DATA = { 0, sizeof(struct __TestCode__testFunc_block_impl_0), __TestCode__testFunc_block_copy_0, __TestCode__testFunc_block_dispose_0};
    

    三:持有变量引用计数操作:

    既然在ARCcopydispose函数都没有对引用计数做修改,那么什么时候会对引用计数进行操作?

    通过对持有变量的分析、可以总结出以下特点

    1. 用__strong 与 __weak修饰

    - (void)testFunc {
        printf("\n Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __weak typeof (self)weakSelf1 = self;
        printf("\n 【__weak typeof (self)weakSelf】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __weak TestCode *weakSelf2 = self;
        printf("\n 【__weak TestCode *weakSelf2】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __strong typeof(self)strongSelf1 = self;
        printf("\n 【__strong typeof(self)strongSelf1】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __strong TestCode *strongSelf2 = self;
        printf("\n 【__strong TestCode *strongSelf2】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        self.block111 = ^{
            [weakSelf1 class];
            [weakSelf2 class];
            [strongSelf1 class];
            [strongSelf2 class];
        };
    }
    
    /** log:
     Retain Count = 1
     【__weak typeof (self)weakSelf】 Retain Count = 1
     【__weak TestCode *weakSelf2】 Retain Count = 1
     【__strong typeof(self)strongSelf1】 Retain Count = 2
     【__strong TestCode *strongSelf2】 Retain Count = 3
    */
    

    编译后的代码:

    static void _I_TestCode_testFunc(TestCode * self, SEL _cmd) {
        printf("...");
        
          __attribute__((objc_ownership(weak))) typeof (self)weakSelf1 = self;  
        __attribute__((objc_ownership(weak))) TestCode *weakSelf2 = self;
      
        __attribute__((objc_ownership(strong))) typeof(self)strongSelf1 = self;
        __attribute__((objc_ownership(strong))) TestCode *strongSelf2 = self;
    
        ((void (*)(id, SEL, void (^ _Nonnull)()))(void *)objc_msgSend)((id)self, sel_registerName("setBlock111:"), ((void (*)())&__TestCode__testFunc_block_impl_0((void *)__TestCode__testFunc_block_func_0, &__TestCode__testFunc_block_desc_0_DATA, strongSelf1, strongSelf2, 570425344)));
    }
    
    
    struct __TestCode__testFunc_block_impl_0 {
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
     
      TestCode *const __weak weakSelf1;
      TestCode *__weak weakSelf2;
      
      __strong typeof (self) strongSelf1;
      TestCode *__strong strongSelf2;
    
      // 同名构造函数
      __TestCode__testFunc_block_impl_0(...){ ... }
    };
    
    
    1. __weak

      __weak TestCode *weakSelf1 = self__weak typeof(self)weakSelf2 = self

      最终都调用了__attribute__((objc_ownership(weak)))

      而且__TestCode__testFunc_block_impl_0中对weakSelf1weakSelf2都是弱引用

    2. __strong

      __strong typeof(self)strongSelf1 = self__strong TestCode *strongSelf2 = self

      最终都调用了__attribute__((objc_ownership(strong)))

      而且__TestCode__testFunc_block_impl_0中对strongSelf1strongSelf2都是强引用

    2. 用__block修饰的对象

    __block修饰的对象分成两种写法

    1. __block TestCode *blockSelf = weakSelf
    2. __block typeof(weakSelf)blockSelf2 = weakSelf
    
    - (void)testFunc {
        printf("\n Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __weak typeof(self)weakSelf = self;
        
        __block TestCode *blockSelf1 = weakSelf;
        printf("\n 【__block TestCode *blockSelf1 = weakSelf】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        __block typeof(weakSelf)blockSelf2 = weakSelf;
        printf("\n 【__block typeof(weakSelf)blockSelf2 = weakSelf】 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
        
        self.block111 = ^{
            [blockSelf1 class];
            [blockSelf2 class];
        };
    }
    
    /**log:
     Retain Count = 1
     【__block TestCode *blockSelf1 = weakSelf】 Retain Count = 2
     【__block typeof(weakSelf)blockSelf2 = weakSelf】 Retain Count = 2
    */
    

    编译上述代码:

    struct __TestCode__testFunc_block_impl_0 {
      
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
        
      __Block_byref_blockSelf1_0 *blockSelf1; // by ref
      __Block_byref_blockSelf2_1 *blockSelf2; // by ref
      
        // 同名构造函数
      __TestCode__testFunc_block_impl_0(...)  { ...  }
    };
    
    struct __Block_byref_blockSelf1_0 {
      void *__isa;
    __Block_byref_blockSelf1_0 *__forwarding;
     int __flags;
     int __size;
     void (*__Block_byref_id_object_copy)(void*, void*);
     void (*__Block_byref_id_object_dispose)(void*);
     TestCode *__strong blockSelf1;
    };
    
    struct __Block_byref_blockSelf2_1 {
      void *__isa;
    __Block_byref_blockSelf2_1 *__forwarding;
     int __flags;
     int __size;
     void (*__Block_byref_id_object_copy)(void*, void*);
     void (*__Block_byref_id_object_dispose)(void*);
     typeof (weakSelf) blockSelf2;
    };
    
    

    __TestCode__testFunc_block_impl_0中生成了两个成员变量

    1. __block TestCode *blockSelf = weakSelf

      TestCode *__strong blockSelf1;self进行了强引用,从而self引用计数+1,从而产生循环引用。

    2. __block typeof(weakSelf)blockSelf2 = weakSelf;

      typeof (weakSelf) blockSelf2self的引用为弱引用,引用计数没有+1操作。

    3. 补充:

    1. 在当前作用域中,对selfretainCount加1,退出作用域后减一
      1. __block typeof(self)blockSelf = self;
      2. __block NSObject *blockSelf = self;
      3. __strong typeof (self)strongSelf = self;
      4. __strong NSObject *strongSelf = self;
    2. selfretainCount不作操作
      1. __weak typeof(self)weakSelf = self;
      2. __weak NSObject *weakSelf = self;

    注意 :

    用这些修饰语句对对象的引用计数只在当前作用域有效。让block产生循环引用的关键在于

    __TestCode__testFunc_block_impl_0 block结构体中对对象是否是强引用。

    思考答案

    @implementation TestCode
    - (void)testFunc {
        @weakify(self)
        self.block111 = ^{
            @strongify(self);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self) {
                    printf("\n\nstrongPerson1 Retain Count = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
                }else{
                    printf("self Retain Count = 0 \n");
                }
            });
        };
    }
    
    - (void)dealloc {
        printf("\n");
        printf("✅ 【dealloc】 Retain Count = 0");
    }
    @end
    

    编译后代码:

    /// block111结构体
    struct __TestCode__testFunc_block_impl_1 {
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_1* Desc;
      
      TestCode *const __weak self_weak_;// 若引用
      
      __TestCode__testFunc_block_impl_1(void *fp, struct __TestCode__testFunc_block_desc_1 *desc, TestCode *const __weak _self_weak_, int flags=0) : self_weak_(_self_weak_) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    
    ///block111中储存的代码
    static void __TestCode__testFunc_block_func_1(struct __TestCode__testFunc_block_impl_1 *__cself) {
      TestCode *const __weak self_weak_ = __cself->self_weak_; // bound by copy
    
            try {} catch (...) {}
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wshadow"
     __attribute__((objc_ownership(strong))) __typeof__(self) self = self_weak_;
    #pragma clang diagnostic pop
    ;
            dispatch_after(dispatch_time((0ull), (int64_t)(2.0 * 1000000000ull)), dispatch_get_main_queue(), ((void (*)())&__TestCode__testFunc_block_impl_0((void *)__TestCode__testFunc_block_func_0, &__TestCode__testFunc_block_desc_0_DATA, self, 570425344)));
        }
    
    
    /// block222结构体
    struct __TestCode__testFunc_block_impl_0 {
        
      struct __block_impl impl;
      struct __TestCode__testFunc_block_desc_0* Desc;
        
      __strong typeof (self) self;/// 强引用
        
      __TestCode__testFunc_block_impl_0(void *fp, struct __TestCode__testFunc_block_desc_0 *desc, __strong typeof (self) _self, int flags=0) : self(_self) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    注意:以下block111是self所持有的block

    • 如果在block111 中对 NSMutableArray *arrayM 进行增删元素, arrayM是否需要用__block修饰?

      答:不需要,因为并没有修改arrayM指针所指向的地址

    • block111 中对weakSelf进行 __strong typeof(weakSelf) strongSelf = weakSelf 修饰

      • 如果block一直不调用,那么self是否可以正常销毁?

        答:可以销毁

        因为block调用的时候,才会创建__TestCode__testFunc_block_impl_0

        使得__TestCode__testFunc_block_impl_0内部对self进行了强引用

        从而只要__TestCode__testFunc_block_impl_0不销毁,self就无法销毁

      • 当运行到__strong typeof(weakSelf) strongSelf = weakSelf的下一行时,self引用计数最少是多少?

        答:最少是2

        但是出了__strong typeof(weakSelf) strongSelf = weakSelf的作用域,self的引用计数就会自动减1

    参考文章

    1. 探索 Block 的本质
    2. iOS底层原理总结 - 探寻block的本质(一)
    3. iOS底层原理总结 - 探寻block的本质(二)
    4. iOS Block Part6:block拷贝的实现
    5. OS - Block底层解析
    6. 一篇文章剖析block底层源码以及Block.private
    7. Block_private.h
    8. runtime.c

    如果有不对的地方欢迎来喷~

    邮箱:15076299703@163.com

    相关文章

      网友评论

          本文标题:OC:深入探究 block

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