block分析

作者: 昵称是乱起的 | 来源:发表于2019-01-28 14:59 被阅读79次
main函数中定义了一个block
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int age = 10;
        void (^block)(void) = ^(void){
            NSLog(@"%d",age);
        };
        block();
    }
    return 0;
}

clang -rewrite-objc main.m执行后看看底层,把影响我们分析代码的强制类型转换全部删掉看更清晰

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        int age = 10;
        void (*block)(void) = &__main_block_impl_0(
                                                   __main_block_func_0,
                                                   &__main_block_desc_0_DATA,
                                                   age);
        block->FuncPtr(block);
    }
    return 0;
}

看下__main_block_impl_0的结构

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int age;
  // 构造函数,返回结构体对象本身
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags=0) : age(_age) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

__main_block_func_0封装了block函数执行代码

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int age = __cself->age; // bound by copy
  NSLog((NSString *)&__NSConstantStringImpl__var_folders__d_dpwms6wj1nqbjv0j93rmzl3h0000gn_T_main_fdaf48_mi_0,age);
 }
static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

block就是一个对象,封装了函数执行代码和执行上下文

block的变量截获捕捉

全局变量、全局静态变量不截获
局部基本数据类型截获其值
局部静态变量截获其指针
对象类型截获对象及其所有权修饰符

__block修饰

需要给对象和局部变量赋值的时候,需要__block修饰,实质就是__block把他们包装成了一个新的对象_Block_byref_age_0, __forwarding指针指向自身

struct __Block_byref_age_0 {
  void *__isa;
__Block_byref_age_0 *__forwarding;
 int __flags;
 int __size;
 int age;
};
3种block的copy操作
image.png image.png image.png

被__block修饰的对象,修改这个对象的值时,其实就是通过栈上这个对象的forwarding的指针找到堆上的对象,然后修改它的值。

block的循环引用

第一个图MRC不会循环引用,ARC会循环引用,改成2图,ARC不会循环引用


image.png image.png

一个对象的成员变量对block强引用,block对象内部又持有该对象,就会引起自循环引用,
把引用的改对象用__weak修饰,
__block修饰MRC不会循环引用
__ARC下需要把__block修饰的对象清空一下,并且调用这个block

相关文章

网友评论

    本文标题:block分析

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