iOS底层 -- Blcok本质之__Block修饰符

2020-09-10  本文已影响0人  happy神悦

一、__Block修饰auto变量

定义一个__block修饰的auto变量

Block block;
__block int age = 10; 
block = ^{
    age = 20;
    NSLog(@"%d", age);
};
block();

编译器会将__block变量包装成一个对象(结构体)

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;
  }
};

struct __Block_byref_age_0 {
 void *__isa;   // isa指针
 __Block_byref_age_0 *__forwarding; // 指向自身的指针
 int __flags;
 int __size; // 结构体的大小
 int age;    // auto变量的值
};

二、__block内存管理

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

2.当block被拷贝到堆上

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {
    _Block_object_assign((void*)&dst->objc, (void*)src->objc, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

3.当block从堆中移除时

static void __main_block_dispose_0(struct __main_block_impl_0*src) {
    _Block_object_dispose((void*)src->objc, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

三、_forwarding指针的作用

复制之前:
age(栈区age结构体)->_forwarding(指向自己的指针)->age(age成员变量值)

复制之后:
age(栈区age结构体)->_forwarding(指向堆区age结构体)->age(age成员变量值)

四、__block修饰对象类型

1.当__block变量在栈上时,不会对指向的对象产生强引用

2.当__block变量被copy到堆时

强引用:

Block block;
__block Person *person = [[Person alloc] init];
block = ^{
    NSLog(@"%@", person);
};

struct __Block_byref_person_0 {
  void *__isa;
  __Block_byref_person_0 *__forwarding;
  int __flags;
  nt __size;
  void (*__Block_byref_id_object_copy)(void*, void*);//从栈上复制到堆上要进行的操作
  void (*__Block_byref_id_object_dispose)(void*);//从堆上移除要进行的操作
  Person *person;//强引用
};

弱引用:

Block block;
Person *person0 = [[Person alloc] init];
__block __weak Person *person = person0;
block = ^{
    NSLog(@"%@", person);
};

struct __Block_byref_person_0 {
  void *__isa;
  __Block_byref_person_0 *__forwarding;
  int __flags;
  int __size;
  void (*__Block_byref_id_object_copy)(void*, void*);//从栈上复制到堆上要进行的操作
  void (*__Block_byref_id_object_dispose)(void*);//从堆上移除要进行的操作
  Person *__weak person;//弱引用
};

3.当__block变量从堆上移除

上一篇下一篇

猜你喜欢

热点阅读