前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >block内存管理

block内存管理

作者头像
老沙
发布2019-09-27 19:29:51
6890
发布2019-09-27 19:29:51
举报
文章被收录于专栏:老沙课堂

1. 在某些ARC情况 会将栈内的block copy到 堆 中

  1. block 在作为函数返回值的时候 会自动copy操作 在函数中作为返回值的时候。生成的是盏中的block 在函数结束后,如果block在盏中,有可能会被销毁,当我们在调用的时候,会发生错误。所以会对block进行 copy操作 copy到堆中,确保后续操作正确.
  2. Block 被强指针引用 int a = 10;void(^test)(void) = ^{ NSLog(@"%d",a);};NSLog(@"%@",[test class]); NSLog(@"%@",[^{ NSLog(@"%d",a); } 打印结果为 ARC 2019-08-21 14:20:55.125206+0800 Block内部实现原理[96810:14357802] __NSMallocBlock__2019-08-21 14:20:55.125244+0800 Block内部实现原理[96810:14357802] __NSStackBlock__
  3. block作为Cocoa API中方法名含有usingBlock方法参数时 例如[Array enum]遍历
  4. GCD中的block

2. copy

盏空间的block 不会对外面capture的变量进行强引用 无论weak修饰 还是strong修饰

堆空间的block 对外面capture的变量进行强引用

__weak 修饰后 block结构体中引用对象也会变成 __weak

当对block进行copy操作的

block desc中会添加两个方法

  • __main_block_copy_0
  • __main_block_dispose

copy会调用block_object_assign函数

Block_object_assign 自动根据capture到的变量的引用是weak还是strong 来进行操作 类似于retain

在block从堆上移除会调用__main_block_dispose

__main_block_dispose会调用_Block_object_dispose_Block_object_dispose函数会自动释放引用的变量, 类似release

3. __block

我们书写下下面代码 然后看一下rewrite-objc 后生成什么

代码语言:javascript
复制
__block NSObject *person = [NSObject new];    void (^testBlock)(void) = ^(void) {  NSLog(@"%@",person);// person 为__block结构体中的person};
代码语言:javascript
复制
__attribute__((__blocks__(byref))) __Block_byref_person_0 person = {            (void*)0,            (__Block_byref_person_0 *)&person,            33554432,            sizeof(__Block_byref_person_0),            __Block_byref_id_object_copy_131,            __Block_byref_id_object_dispose_131,            ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("new"))};

当被__block 修饰后的persion 会被构造到个结构体__Block_byref_person_0

代码语言:javascript
复制
struct __Block_byref_person_0 {  void *__isa;  // isa  __Block_byref_person_0 *__forwarding; //指向自己的指针 当block从栈copy到堆中  则指向堆中block的地址 int __flags; // 标记 int __size; // 大小 void (*__Block_byref_id_object_copy)(void*, void*); // 当block被拷贝到堆中执行此方法 void (*__Block_byref_id_object_dispose)(void*);  // 当block释放 执行这个方法 NSObject *person; //persion};

在ARC环境下 block在赋值的时候 会发生拷贝。具体的指向由下图所示。

__block __weak NSObject *person = [NSObject new]; 修饰符为weak时 弱引用 其他时候为强引用

这样的结构的好处是无论我们从栈中去找block找到__forwrding 还是堆中block__forwarding找person的时候,都能够找到堆中的block 中的person 这样就确保person的存在。

4. 循环引用

__weak unsafe_unretain __block 里面

因为__block生成的结构体类似中间变量,所以在循环引用个的时候是一个三角结构,我们在在block中将__block修饰的变量置为nil 既可解决循环引用。如下图

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老沙说点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 在某些ARC情况 会将栈内的block copy到 堆 中
  • 2. copy
  • 3. __block
  • 4. 循环引用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档