美文网首页
【iOS面试粮食】Block

【iOS面试粮食】Block

作者: KaironZz | 来源:发表于2019-12-19 15:57 被阅读0次

    本文章将记录Objective-C中Block的相关资料,如有错误欢迎指出~

    Block的本质

    Block本质.png

    Block 实际上就是一个OC对象(结构体中有 isa 指针),这个对象封装了函数,以及函数执行的上下文

    Block的变量捕获

    为了保证block内部能够正常访问外部的变量,block有一个变量捕获机制。block捕获外部变仅仅只捕获Block闭包里面会用到的值,其他用不到的值,它并不会去捕获。

    局部变量

    看下简单的代码输出

    auto int age = 10;
    static int num = 25;
    void (^Block)(void) = ^{
        NSLog(@"age:%d,num:%d",age,num);
    };
    age = 20;
    num = 11;
    Block();
    
    // log   age = 10
                     age = 11
    
    • auto变量
      • auto自动变量,离开作用域就销毁,通常局部变量前面自动添加auto关键字。自动变量会捕获到block内部,也就是说block内部会专门新增加一个参数来存储变量的值。 auto只存在于局部变量中,访问方式为值传递。
    • static变量
      • static 修饰的变量为指针传递,同样会被block捕获。

    为什么两种变量会有这种差异呢?

    因为自动变量可能会销毁,block在执行的时候有可能自动变量已经被销毁了,那么此时如果再去访问被销毁的地址肯定会发生坏内存访问,因此对于自动变量一定是值传递而不可能是指针传递了。

    而静态变量不会被销毁,所以完全可以传递地址。而因为传递的是值得地址,所以在block调用之前修改地址中保存的值,block中的地址是不会变得。所以值会随之改变。

    全局变量

    因为全局变量无论在哪里都可以访问,所以block不需要捕获全局变量

    变量类型

    总结:

    • 局部变量都会被block捕获,自动变量是值捕获,静态变量为地址捕获

    • 全局变量则不会被block捕获

    Block的类型

    OC中,一般Block就分为以下3种类型

    • __NSGlobalBlock__( _NSConcreteGlobalBlock ),即没有用到外界变量或只用到全局变量、静态变量的block。生命周期从创建到应用程序结束,直到程序结束才会被回收,不过我们很少使用到__NSGlobalBlock__类型的block,因为这样使用block并没有什么意义。
    • __NSStackBlock__( _NSConcreteStackBlock ),即只用到外部局部变量、成员属性变量,且没有强指针引用的block。__NSStackBlock__类型的block存放在栈中,我们知道栈中的内存由系统自动分配和释放,作用域执行完毕之后就会被立即释放,而在相同的作用域中定义block并且调用block似乎也多此一举。
    • __NSMallocBlock__( _NSConcreteMallocBlock ),即有强指针引用或copy修饰的成员属性引用的block 。存放在堆中,没有强指针引用即销毁,需要我们自己进行内存管理。
    Block的类型.png

    Block的循环引用

    这篇文章讲的挺不错的Block 与 self 的那点事(iOS)

    面试题

    面试题请参考 这篇文章 iOS-Block相关面试题

    参考

    iOS底层原理总结 - 探寻block的本质(一)

    iOS block 捕获外部变量以及注意点

    相关文章

      网友评论

          本文标题:【iOS面试粮食】Block

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