美文网首页悦览树
iSO底层原理 - Block的本质

iSO底层原理 - Block的本质

作者: 南城同學 | 来源:发表于2017-08-21 09:19 被阅读0次
Block的本质:
  • block本质上也是一个OC对象,它内部也有个isa指针;
  • block是封装了函数调用以及函数调用环境的OC对象;

Block的数据结构
Block的数据结构
block的变量捕获(capture)
  • 为了保证block内部能够正常访问外部的变量,block有个变量捕获机制;
    1.局部变量需要捕获;
    2.全局变量不需要捕获,直接访问就可以。

  • 捕获机制
局部变量
        // auto:自动变量,离开作用域就销毁
        //默认就是auto
        auto int age = 10; 
        static int height = 10;
        void (^block)(void) = ^{
            // age的值捕获进来(capture)
            NSLog(@"age is %d, height is %d", age, height);
        };
        age = 20;
        height = 20;
        block();
  • 打印结果是:age = 10; height = 20。
  • 底层结构如下:
struct __test_block_impl_0 {
  struct __block_impl impl;
  struct __test_block_desc_0* Desc;
  int age;
  int *height;
  __test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int _age, int *_height, int flags=0) : age(_age), height(_height) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

1> 创建block的时候,直接 auto修饰 的age封装到了block中了,block外再修改,不会影响block内部的age;
2> static修饰的height,传到block内部的是一个指针;外部修改,也会影响block内部的结果。

为何这样设置 ?
  • 因为 auto修饰的局部变量,离开作用域后就会销毁;如果也采用指针访问,那此时访问到的就是垃圾数据。
扩展 :self 会被捕获吗 ?
- (void)test {
    void (^block)(void) = ^{
        NSLog(@"-------%p", self);
    };
    block();
}
  • 会;
  • self其实是一个参数,参数是一个局部变量。
// test函数完整写法如下:
- (void)test(Object *self, SEL _cmd) {
}


相关文章

网友评论

    本文标题:iSO底层原理 - Block的本质

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