最认真的Block

作者: MrBMask | 来源:发表于2018-12-22 19:50 被阅读0次

    block的本质:

    1.block的本质其实就是一个oc对象(内部有isa指针),内部封装了函数调用和函数调用(函数参数)的oc对象。
    2.block的底层结构如图:


    block的底层结构.png

    2.block捕获机制:

    为了保证block能够正常访问外部的变量,block有个变量捕获机制。

    block捕获机制.jpg

    3.block类型:

    block类型
    block在内存中的分配
    • 总结:


      image.png

      每一种block在调用copy之后的类型:


      image.png

    4.block的copy

    在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况:

    • block作为函数返回值时:
      1.将block赋值给__strong指针时
      2.block作为Cocoa API中方法名含有usingBlock的方法参数时
      3.block作为GCD API的方法参数时

    • MRC下block属性的建议写法
      @property (copy, nonatomic) void (^block)(void);

    • ARC下block属性的建议写法
      @property (strong, nonatomic) void (^block)(void);
      @property (copy, nonatomic) void (^block)(void);

    5.对象类型的auto变量

    • 当block内部访问了对象类型的auto变量时
      如果block是在栈上,将不会对auto变量产生强引用

    • 如果block被拷贝到堆上

    1. 会调用block内部的copy函数
      copy函数内部会调用_Block_object_assign函数
      _Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用
    • 如果block从堆上移除
      会调用block内部的dispose函数
      dispose函数内部会调用_Block_object_dispose函数
      _Block_object_dispose函数会自动释放引用的auto变量(release)


      image.png

    6.__block修饰符和内存管理

    • __block修饰符的作用:
      __block可以用于解决block内部无法修改auto变量值的问题

    __block不能修饰全局变量、静态变量(static)

    编译器会将__block变量包装成一个对象

    • 内存管理:
      一.当block在栈上时,并不会对__block变量产生强引用
      二.当block被copy到堆时:
      1.会调用block内部的copy函数
      2.copy函数内部会调用_Block_object_assign函数
      3._Block_object_assign函数会对__block变量形成强引用(retain)

    • 被__block修饰的对象类型
      1.当__block变量在栈上时,不会对指向的对象产生强引用
      2.当__block变量被copy到堆时
      3.会调用__block变量内部的copy函数
      copy函数内部会调用_Block_object_assign函数
      _Block_object_assign函数会根据所指向对象的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用(注意:这里仅限于ARC时会retain,MRC时不会retain

    如果__block变量从堆上移除
    会调用__block变量内部的dispose函数
    dispose函数内部会调用_Block_object_dispose函数
    _Block_object_dispose函数会自动释放指向的对象(release)

    7.解决循环引用问题 - ARC

    1.用__weak、__unsafe_unretained解决:
    __weak 对象销毁时系统会自动置为nil,__unsafe_unretained会产生野指针


    image.png

    2.用__block解决(必须要调用block):


    image.png

    8.解决循环引用问题 - MRC

    1.用__unsafe_unretained解决:


    image.png

    2.用__block解决:


    image.png

    相关文章

      网友评论

        本文标题:最认真的Block

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