iOS技巧汇总

iOS Block 内存管理,__block修饰变量值的原理(为

2019-12-16  本文已影响0人  孙掌门

Block 内存管理,__block修饰变量值的原理(为什么改变值要用__Block 修饰)

根据上篇文章,将文件编译为 cpp 文件,通过查看 block 的结构体

struct __block__testBlock_block_impl_0 {
  struct __block_impl impl;
  struct __block__testBlock_block_desc_0* Desc;
  int i;
  __unsafe_unretained id unsafe_obj;
  __strong id strong_obj;
  int *static_int;
  __block__testBlock_block_impl_0(void *fp, struct __block__testBlock_block_desc_0 *desc, int _i, __unsafe_unretained id _unsafe_obj, __strong id _strong_obj, int *_static_int, int flags=0) : i(_i), unsafe_obj(_unsafe_obj), strong_obj(_strong_obj), static_int(_static_int) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

impl.isa = &_NSConcreteStackBlock;用来标识是哪种类型的 block

三种 block 类型

1. _NSConcreteGlobalBlock // 全局block
2. _NSConcreteStackBlock // 栈block
3. _NSConcreteMallocBlock // 堆 block

block 的 copy 操作,修改值的原理,__forwarding 作用

--- --- ---
block类别 原位置 copy之后结果
_NSConcreteStackBlock
_NSConcreteGlobalBlock 数据区 不做任何事情
_NSConcreteMallocBlock 增加引用计数

栈block在作用于结束之后,对应的block也会销毁

当在栈上对block进行copy之后,会在堆上copy一份,当栈上变量作用于结束之后,栈block 会销毁,但是堆上会存在。

所以在mrc对blockcopy之后,容易造成内存泄漏,因为堆上没有释放.

我们的栈上 block 有一个 __Block 变量,同时还有个__forwarding 指针,指向他自己,当进行copy之后,会在堆上也有一份,同时也会有, __Block变量和 __forwarding 指针,这里面的__forwarding指针的用途是什么呢?当进行copy之后,栈上的__forwarding指针指向堆上的 __Block变量,而堆上的__forwarding指针,也指向自身的
__Block变量,所以当我们要修改一个值得时候用 __Block指针来修饰,原因是,这时候已经将 栈上面的block,copy 到了堆上面,当我们修改变量的值得时候,其实就是通过栈上面的那个__forwarding指针找到堆上面的__block变量,然后修改堆上面的__Block修饰的变量的值,如果我们这个block被成员变量或者其他地方持有的话,那么实际上就是通过堆上面自身的变量的值,所以可以总结,当我们的栈block经过copy之后,堆上面会有一份,都是通过 __forwarding指针,找到__block变量,然后修改他的值。

上一篇下一篇

猜你喜欢

热点阅读