iSO底层原理 - Block的本质

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) {
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容