美文网首页
Block原理

Block原理

作者: CoderLF | 来源:发表于2018-04-16 22:44 被阅读5次
为什么不允许block修改外部变量

Block不允许修改外部变量的值Apple这样设计,应该是考虑到了block的特殊性,block也属于“函数”的范畴,变量进入block,实际就是已经改变了作用域。在几个作用域之间进行切换时,如果不加上这样的限制,变量的可维护性将大大降低。又比如我想在block内声明了一个与外部同名的变量,此时是允许呢还是不允许呢?只有加上了这样的限制,这样的情景才能实现。

在block内如何修改block外部变量?

默认情况下,在block中访问的外部变量是复制过去的,即:写操作不对原变量生效。但是你可以加上 __block 来让其写操作生效。

我们都知道:Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。__block 所起到的作用就是只要观察到该变量被 block 所持有,就将“外部变量”在栈中的内存地址放到了堆中,同时block也会被复制到堆中,进而在block内部也可以修改外部变量的值。

  • 对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的,变量是以值传递方式传递到Block的构造函数里面去的。Block只捕获Block中会用到的变量。由于只捕获了自动变量的值,并非内存地址,所以Block内部不能改变自动变量的值。Block捕获的外部变量可以改变值的是静态变量,静态全局变量,全局变量

  • 对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的,此时block内的变量和外部的变量是同一个。

对于非对象的变量被block使用来说:
  • 自动变量的值,被copy进了Block,不带__block的自动变量只能在里面被访问,并不能改变值。

  • 带__block的自动变量 和 静态变量 就是直接地址访问。所以在Block里面可以直接改变变量的值。

  • 而剩下的静态全局变量,全局变量,函数参数,也是可以在直接在Block中改变变量值的,但是他们并没有变成Block结构体__main_block_impl_0的成员变量,因为他们的作用域大,所以可以直接更改他们的值。
    值得注意的是,静态全局变量,全局变量,函数参数他们并不会被Block持有,也就是说不会增加retainCount值。

用__block修饰的变量可以在block中被修改的原理:

  • 没有用__block修饰的自动变量的值以成员变量的形式被保存到Block的结构体实例(或者说被其持有),通过__cself被使用;
  • 被__block修饰的变量,则转化成结构体,其指针作为成员变量保存到Block结构体中
在Block中修改自动变量的两种方法:
  • 静态变量、静态全局变量或全局变量
  • __block存储域类说明符 - 类似于static、auto和register说明符,指定将变量值设置到哪个存储域中。
对于对象来说:
  • 在MRC环境下,__block根本不会对指针所指向的对象执行copy操作,而只是把指针进行的复制。
  • 而在ARC环境下,对于声明为__block的外部对象,在block内部会进行retain,以至于在block环境内能安全的引用外部对象。
什么时候栈上的Block会被复制到堆上呢?

1、调用Block的copy实例方法时
2、 Block作为函数返回值返回时
3、将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时
4、在方法名中含有usingBlock的Cocoa框架方法或GCD的API中传递Block时

循环引用问题

原因:Block中附有__strong修饰符的对象类型自动变量在从栈复制到堆上时,该对象会被Block所持有。

解决方案:

  • ARC:通过 __weak 或 __unsafe_unretained 修饰符(iOS4)来替代 __strong 类型的被截获的自动变量
    通过 __block 说明符和设置nil来打破循环
  • MRC:通过 __block 说明符指定变量不被Block所retain;ARC下__block说明符的作用仅限于使其能在Block中被赋值。

原理:
如果对block做一次copy操作, block的内存就会在堆中

  • 它会对所引用的对象做一次retain操作
  • 非ARC : 如果所引用的对象用了__block修饰, 就不会做retain操作
  • ARC : 如果所引用的对象用了__unsafe_unretained__weak修饰, 就不会做retain操作

参考文章1
参考文章2

相关文章

网友评论

      本文标题:Block原理

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