美文网首页悦览树
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