美文网首页
IOS block原理详解

IOS block原理详解

作者: 有梦想的狼 | 来源:发表于2020-01-20 14:38 被阅读0次

block的本质:

  • block本质上也是一个OC对象,它内部也有isa指针。
  • block是封装了函数以及函数调用环境的OC对象。
  • block底层结构如下图:
block底层结构

block的变量捕获:

  • 局部变量:
    auto:值捕获。
    static:指针捕获。
  • 全局变量:直接访问。

block的类型:

  • NSGlobalBlock:
    在内存的数据区域.data区,是没有访问auto局部变量。当调用copy后,没有任何的改变,依然在数据区域。
  • NSStacklBlock:
    在内存的栈中,是访问了auto局部变量。当调用copy后,从栈中复制到堆中。
  • NSMallocBlock:
    在内存的堆中,NSStacklBlock调用了copy。当调用copy后,引用计数器+1。

block的copy:

  • 在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上。
    block属性的建议写法:
@property (strong, nonatomic) void (^block)(void);
@property (copy, nonatomic) void (^block)(void);
  • 在MRC环境下,在栈上的block要进行copy操作,复制到堆上。
    block属性的建议写法:
@property (copy, nonatomic) void (^block)(void);

对象类型的auto局部变量:

  • 如果block是在栈上:
    不会对auto局部变量产生强引用。
  • 如果block被copy到堆上:
    1.1 会调用block内部的copy函数
    1.1.1 copy函数内部会调用_Block_object_assign函数
    1.1.1.1 _Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用。
  • 如果block从堆上移除
    1.1 会调用block内部的dispose函数
    1.1.1 dispose函数内部会调用_Block_object_dispose函数
    1.1.1.1 _Block_object_dispose函数会自动释放引用的auto变量(release)。

__block修饰符:

添加__block的变量,编译器会将该变量包装成一个对象,如下图: 包装后
  • 作用:
    __block可以用于解决block内部无法修改auto 局部变量值的问题。(因为auto局部变量在block中是值传递捕获,auto局部变量是在栈中,程序执行完该作用域,就会被销毁,所以需要通过__block把auto局部变量放在堆中,当auto变量加上__block修饰符时,会把该变量封装成一个block结构体,在这个结构体中有个forwarding指针,指向自身,并且这个结构体中包含有auto变量)
  • 注意:
    __block不能修饰全局变量、静态变量(static)。

对象类型的__block局部变量

  • 如果__block是在栈上:
    不会对指向的对象产生强引用。
  • 如果__block被copy到堆上:
    1.1 会调用__block内部的copy函数
    1.1.1 copy函数内部会调用_Block_object_assign函数
    1.1.1.1 _Block_object_assign函数会根据__block变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用。(注意:这里仅限于ARC时会retain,MRC时不会retain)
  • 如果block从堆上移除:
    1.1 会调用block内部的dispose函数
    1.1.1 dispose函数内部会调用_Block_object_dispose函数
    1.1.1.1 _Block_object_dispose函数会自动释放引用的__block变量(release)。
  • __block的_forwarding指针: _forwarding指针

block循环引用:

对象持有block,block中又持有对象自己,会造成对象和block无法释放。

解决方案:

  • 在ARC中
    方法一:可以使用__weak修饰符(不会产生强引用,指向的对象销毁时,会自动让指针置为nil)。
__weak修饰符

方法二:可以使用__unsafe_unretained修饰符(不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变)。

__unsafe_unretained修饰符

方法三:可以使用__block修饰符(必须调用block,并在执行完block中的内容后,把修饰的该对象置为nil)。

__block修饰符
  • 在MRC中(在MRC情况下,不支持弱引用__weak)
    方法一:可以使用__unsafe_unretained修饰符(不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变)。
__unsafe_unretained

方法二:可以使用__block修饰符(因为在MRC中,__block不会对持有对象进行强引用retain)。

__block修饰符

相关文章

  • iOS Block实例

    iOS之Block详解:Block详解 ViewController.h(ARC) ViewController....

  • iOS-2 Block

    block块 系列文章: iOS Block浅浅析 - 简书 iOS Block实现原理 iOS Block __...

  • iOS block原理详解

    block本质 block底层就是一个struct __main_block_impl_0类型的结构体,这个结构体...

  • IOS block原理详解

    block的本质: block本质上也是一个OC对象,它内部也有isa指针。 block是封装了函数以及函数调用环...

  • iOS Block存储域及循环引用

    系列文章:iOS Block概念、语法及基本使用iOS Block实现原理iOS Block __block说明符...

  • Objective-C的本质(6)——Block本质

    参考:iOS-Block本质iOS底层原理总结 - 探寻block的本质(一)iOS底层原理总结 - 探寻bloc...

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

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

  • Block

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

  • iOS Block __block说明符

    系列文章:iOS Block概念、语法及基本使用iOS Block实现原理iOS Block存储域及循环引用 上一...

  • iOS 题目详解 部分三

    主要讲解Block 内部使用strongSelf的理由和用法 iOS 题目详解 部分一iOS 题目详解 部分二...

网友评论

      本文标题:IOS block原理详解

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