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

iOS中block块的存储位置&内存管理

作者头像
Cloudox
发布2021-11-23 14:08:41
1.2K0
发布2021-11-23 14:08:41
举报
文章被收录于专栏:月亮与二进制月亮与二进制

block是iOS开发中一种使用方便的代码块,但是在使用过程中也很容易不小心就造成问题,本文讲解其存储位置所决定的内存修饰以及如何避免循环引用。

iOS内存分区

先讲讲大的,关于iOS在内存中的分区情况。

内存分为五个区:栈区、堆区、全局区、常量区、代码区。这五个区在物理上是分开的,如下图所示:

这五个区存储的内容也各有划分:

  • 栈区(stack):这一块区域系统会自己进行管理,我们不用干预,主要存一些局部变量,以及函数跳转时的现场保护。因此大量的局部变量、深递归、函数循环调用都可能耗尽内存而造成运行崩溃。
  • 堆区(heap):与栈区相对,这一块一般由我们开发人员管理,比如一些alloc、free的操作,存储一些自己创建的对象。
  • 全局区(静态区 static):全局变量和静态变量都存储在这里,已经初始化的和没有初始化的变量会分开存储在相邻的区域,程序结束后系统来释放。
  • 常量区:存储常量字符串和const常量。
  • 代码区:顾名思义,就是存我们写的代码。

block块存储位置

block块根据情况有两种可能的存储位置,一种存在代码区,一种存在堆区。

1、如果block块没有访问处于栈区的变量(比如局部变量),也没有访问堆区的变量(比如我们alloc创建的对象),那就存在代码区,即使访问了全局变量,也依然存在代码区。

2、如果访问了栈区或者堆区的变量,那就会被存在堆区(实际存在栈区,ARC下会自动拷贝到堆区)。

关于存在堆区的情况,有一点需要注意的是,堆区是不断变化的,不断地有变量的创建和销毁,如果block块没有强引用,那也随时可能被销毁,这就导致一旦在销毁时访问block块,程序就会崩溃,所以,在定义block时,内存修饰最好用strong或者copy。而且在使用时也最好先判断一下block是否为空,比如:

代码语言:javascript
复制
if (!block) {
    return;
}
block();

循环引用

既然在修饰block时,使用了strong,那么另一个问题就需要注意了,也就是循环引用。

当使用了strong修饰后,self会强引用block,而如果在block中又需要访问self的一些属性或者方法,从而调用了self,这时self和block就进入循环引用,容易内存溢出。

解决的办法时在block中的需要用到self时,事先将self用__weak修饰,这样互相引用的一方就不再是强引用了。

比如:

代码语言:javascript
复制
__weak ViewController *weakSelf = self;
self.block = ^{
    weakSelf.str = @"123";
};

但是这样还不够,在多线程下,单单使用weakSelf,可能前一刻weakSelf还在,后面需要用时却被释放掉了,毕竟弱引用是不稳定的,这时候就需要又使用一个修饰符__strong来在block中修饰,是不是操碎了心。

因此更好的释放方式如下:

代码语言:javascript
复制
__weak __typeof(self) *weakSelf = self;
self.block = ^{
    __strong __typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
        strongSelf.str = @"123";
    }
    // 如果不用了,应置为空
    strongSelf.block = nil;
};

平常使用block的情况很多,很多人往往都是直接拿样例代码改着用了,不知道为什么要这么修饰block,也不知道weakSelf、strongSelf有什么用。这里就从存储位置来解释为什么要这样修饰block,从而又会造成循环引用的问题,最后如何去解决他。希望可以帮助大家更好的理解手中的每一行代码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/11/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • iOS内存分区
  • block块存储位置
  • 循环引用
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档