OC中的__block修饰符

__block修饰符

__block可以用于解决block内部无法修改auto变量值的问题, __block不能修饰全局变量、静态变量

写下面的block代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block int age = 0;
        void(^test)(void) = ^{
            age = 10;
            NSLog(@"%d",age);
        };
        test();
    }
    return 0;
}

经过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m转为C++代码后,

关键代码如下:

static struct __test1_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __test1_block_desc_0_DATA = { 0, sizeof(struct __test1_block_impl_0)};
void test1() {

    block = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA));

}

struct __Block_byref_age_0 {
  void *__isa;
__Block_byref_age_0 *__forwarding;
 int __flags;
 int __size;
 int age;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_age_0 *age; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

变量在被__block修饰后,会被包装成__Block_byref_变量_0的一个对象,该变量会被copy到堆上。

当block在栈上时,并不会对__block变量产生强引用

当block被copy到堆时,会调用block内部的copy。copy函数内部会调用_Block_object_assign函数

_Block_object_assign函数会对__block变量形成强引用

NSObject *object = [[NSObject alloc] init];
__block NSObject *tempObject = object;
void(^test)(void) = ^{
   NSLog(@"%p",tempObject);
}; test();

转为C++之后,会进行强引用:

struct __Block_byref_tempObject_0 {
  void *__isa;
__Block_byref_tempObject_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSObject *__strong tempObject;
};

进行__weak修饰之后,

NSObject *object = [[NSObject alloc] init];
 __block __weak NSObject *tempObject = object;
 void(^test)(void) = ^{
      NSLog(@"%p",tempObject);
 };
 test();

转为C++代码:

struct __Block_byref_tempObject_0 {
  void *__isa;
__Block_byref_tempObject_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSObject *__weak tempObject;
};

当block从堆中移除时,会调用block内部的dispose函数,dispose函数内部会调用_Block_object_dispose函数

_Block_object_dispose函数会自动释放引用的__block变量(realse)

posted @ 2020-12-16 23:03  木子沉雨  阅读(356)  评论(0编辑  收藏  举报