【iOS】didReceiveMemoryWarning实例方法

news2024/11/27 16:36:15

iPhone下每个App可用的内存是被限制的,如果一个App使用的内存超过20M,则系统会向该App发送Memory Warning(内存警告)消息,收到此消息后,App必须正确处理,否则可能出错或出现内存泄漏。

目录

    • 流程
    • iOS 6以上版本的App对内存警告处理方法
    • 相关方法
      • loadView
      • loadView
      • viewDidLoad
      • awakeFromNib
      • initWithCoder
    • 结论


官方文档:

请添加图片描述

重写didReceiveMemoryWarning方法:

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    NSLog(@"didReceiveMemoryWarning");
}

请添加图片描述

流程

当应用可用内存过低导致系统发出内存警告的时候,便会触发didReceiveMemoryWarning方法。App收到内存警告会调用:

UIApplication::didRecieveMemoryWarning -> UIApplicationDelegate::applicationDidRecieveMemoryWarning

然后调用当前所有的viewController进行处理,因此处理的主要工作在viewController。
创建viewController时,执行顺序是loadView -> viewDidLoad
当收到内存警告时,didRecieveMemoryWarning会判断当前viewController的view是否显示在window上:

  1. 如果viewController未显示(在后台),会执行didRecieveMemoryWarning -> viewDidUnload,前者会自动将viewController的view及其所有子view全部销毁
  2. 如果viewController当前正在显示(在前台),则只执行didRecieveMemoryWarning ,viewController的view不会被销毁
  3. 当重新显示该viewController时,执行过viewDidLoad的viewController(即原来在后台)会重新调用loadView -> viewDidLoad

iOS 6以上版本的App对内存警告处理方法

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];  //super调用的此方法即使没有显示在window上(在后台),也不会自动的将self.view释放。
    //此处做兼容处理需要加上iOS 6.0的宏开关,保证是在6.0下使用的,6.0以前屏蔽以下代码,否则会在下面使用self.view时自动加载viewDidUnLoad
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) {
        //需要注意的是self.isViewLoaded是必不可少的,其他方式访问视图会导致它加载 ,在WWDC视频也忽视这一点。
        if (self.isViewLoaded && !self.view.window) { // 是否是正在使用的视图
            //code
            self.view = nil;// 目的是再次进入时能够重新加载调用viewDidLoad函数。
        }
    }
}
  • iOS 6之前:viewDidUnloaddidReceiveMemoryWarning都会被调用。
  • iOS 6之后:viewDidUnload不会被调用didReceiveMemoryWarning依然被调用。系统会自动处理View相关的内存,我们不用担心。也就是说不再支持viewDidUnload了。
    官方文档的解释是:系统会自动控制大的View所占用的内存,其他小的View所占用的内存是极其微小的,不值得为了省内存而去清理然后在重新创建。 如果你需要在内存警告的时候释放业务数据或者做些其他的特定处理,你可以实现didRecieveMemory方法。

苹果官方给出的相关解释方案总是美好的,但现实往往是残酷的:

  1. 我们的工程是ARC的。
  2. 我们会在viewController里面强持有(strong)大量子View得成员变量
  3. 我们实现了大量的viewDidUnload函数来释放(2)里面持有的那个子View

让我们看看我们的代码到了iOS6以后会发生什么事情。因为所有的子View都是strong持有的,这样会导致,即使系统内存警告导致了View的回收,他们也不会被真正的释放。于是乎,我们的程序可能就在后台被系统频繁的杀死。

栗子🌰:

一个App有三个tab(选项卡界面元素,比如“首页”、“通知”和“消息”的tabs):tabA、tabB、tabC(都从viewController继承,并且都实现了didRecieveMemoryWarning)。当程序启动时,默认显示tabA,这时,tabA的viewDidLoad被调用,并且加载数据显示给用户,然后切换到tabB,B会重复A的加载过程。
这时系统产生了一个内存警告,tabA、tabB、tabC三个对象都会受到警告。

  • tabA对象:因为它已经不在当前UI显示了,所以满足[self.view window] == nil,相关View被释放。
  • tabB对象:正在显示,所有didReceiveMemoryWarning什么也不会干。
  • tabC对象:最悲惨,从来没有显示过,viewDidLoad从来没调用过,也没有显示过。然后有个self.view .这句的调用会导致一个结果,就是C对象的viewDidLoad会被调用一次,于是他的逻辑就是释放前先创建一次,然后再把自己释放,是不是很悲剧。(所以apple给的方案也不一定完美靠谱)。

iOS 6之后,应该做的:

  1. 不要把子View当成员变量来持有,使用tag来操作(其实不管在哪个版本最后都这么做)。
  2. 不需要实现viewDidLoad,由系统自己来控制相关的内存释放。
  3. 在需要的时候实现didRecieveMemory来释放一些业务数据减少内存的占用,不要操作UIView。

相关方法

loadView

loadView

viewDidLoad

awakeFromNib

initWithCoder

正在学习…loadView / viewDidLoad / awakeFromNib / initWithCoder 总结

结论

所以流程应该是这样:
(loadView/nib文件)来加载view到内存 ——>viewDidLoad函数进一步初始化这些view ——>内存不足时,调用viewDidUnload函数释放views —->当需要使用view时又回到第一步

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1708546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

查询DQL

016条件查询之等量关系 条件查询语法格式 select ... from... where过滤条件;等于 select empno, ename from emp where sal3000;select job, sal from emp where enameFORD;select grade, losal, hisal from salgrade where grade 1;不等于 <> 或 ! selectempno,en…

JS逆向之企名科技

文章目录 初步分析定位js编写完整代码参考文献初步分析 目标网址:企名科技 抓包分析,发现是post请求 请求代码如下: #!/usr/bin/env python3 # -*- coding: utf-8 -*- import requestsheaders = {Connection:

MySQL 数据类型和搜索引擎

文章目录 【 1. 数据类型 】1.1 数值类型1.1.1 整型1.1.2 小数1.1.3 数值类型的选择 1.2 日期和时间YEAR 年TIME 时间DATE 日期DATETIME 日期时间TIMESTAMP 时间戳日期和时间的选择 1.3 文本字符串CHAR 固定字符串、VARCHAR 可变字符串TEXT 文本ENUM 枚举SET 集合字符串类型的选…

错误提示:“由于找不到steam_api.dll,无法继续执行代码”修复方法,缺少steam_api.dll文件原因

在尝试运行某些游戏或程序时&#xff0c;用户可能会遇到一个常见的错误提示&#xff1a;“由于找不到steam_api.dll&#xff0c;无法继续执行代码”。这个错误信息表明&#xff0c;系统在启动程序或游戏时无法定位到必要的steam_api.dll文件&#xff0c;这是一个关键的动态链接…

SwiftUI初探

SwiftUI 虽然出现了好几年(1.0好像2019年出的&#xff0c;还有SPM也是同一年)&#xff0c;现在已经到从1.0到5.0&#xff0c;但受限于对系统的要求(最低iOS13.0,有的要求17.0及以上)&#xff0c;每个版本里面差异也很大&#xff0c;语法和Flutter 的Dart 比较像。空闲之余可以先…

黑马es0-1实现自动补全功能

1、安装分词器 上github上找人做好的分词器&#xff0c;放到es-plugin数据卷里&#xff0c;然后重启es即可 2、自定义分词器 elasticsearch中分词器(analyzer)的组成包含三部分: character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符 …

【Python编程实战】基于Python语言实现学生信息管理系统

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

若依ruoyi-vue element-ui 横向滚动条 动态横向滚动条

动态横向滚动条 因为每次横向滑动都要到底部&#xff0c;引入插件 https://github.com/mizuka-wu/el-table-horizontal-scroll //动态横向滚动条移入样式 .el-table-horizontal-scrollbar :hover{//高度 变大10%transform: scaleY(1.5) translateY(-10%);//百分之八十亮度&a…

阻塞、非阻塞、同步与异步IO的区别

IO读取数据的过程 如图所示&#xff0c;进程读取数据的过程主要分为两个步骤 1.内核将数据准备好到内核缓冲区 2.内核将数据拷贝到用户态 在上述这两个过程里&#xff0c;进程首先和内核打交道&#xff0c;之后内核再和硬件&#xff08;如网卡&#xff09;打交道 阻塞IO 如图所…

将 KNX 接入 Home Assistant 之二 准备软件

写在前面&#xff1a; 在KNX官网也有关于 Home Assistant 的教程&#xff0c;地址是 Get started with Home Assistant x KNX 需要的东西是 a KNX IP Interface or Routera Raspberry Pian SD Card at least 32 GB 安装 Home Assistant 系统 下载镜像&#xff1a; 地址&…

【调试笔记-20240522-Windows-WSL 修改已安装发行版名称】

调试笔记-系列文章目录 调试笔记-20240522-Windows-WSL 修改已安装发行版名称 文章目录 调试笔记-系列文章目录调试笔记-20240522-Windows-WSL 修改已安装发行版名称 前言一、调试环境操作系统&#xff1a;Windows 10 专业版调试环境调试目标 二、调试步骤方法一&#xff1a;修…

3步找回丢失数据,EasyRecovery让数据恢复如此简单!

在数字化时代&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;数据丢失却是一个令人头疼的问题。无论是因为意外删除、硬盘损坏还是系统崩溃&#xff0c;丢失的文件和数据都可能给我们造成巨大的经济损失和时间浪费。因此&#xff0c;如何高效利用现…

Python内置方法串讲:类型转化与实用技巧

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、类型转化&#xff1a;从A到B的魔法 二、实用技巧&#xff1a;避免类型错误 三、总结 一…

【安装笔记-20240519-Windows-安装测试 PuTTY】

安装笔记-系列文章目录 安装笔记-20240521-Windows-安装测试 PuTTY 文章目录 安装笔记-系列文章目录安装笔记-20240521-Windows-安装测试 PuTTY 前言一、软件介绍名称&#xff1a;PuTTY主页官方介绍 二、安装步骤测试版本&#xff1a;0.81下载链接安装步骤功能界面 三、应用场…

列表、元组、字典和集合的区别

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在前面介绍了序列中的列表、元组、字典和集合的应用&#xff0c;下面通过表2对这几个数据序列进行比较。 表2 列表、元组、字典和集合的区别 数 据…

设计模式18—— 迭代器模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 迭代器模式&#xff08;Iterat…

LiveGBS流媒体平台GB/T28181用户手册-操作日志:HTTP接口记录、上级SIP信令、搜索、清空

LiveGBS流媒体平台GB/T28181用户手册-操作日志:HTTP接口记录、上级SIP信令、搜索、清空 1、操作日志1.1、列表1.2、搜索过滤1.3、清空 2、搭建GB28181视频直播平台 1、操作日志 操作日志&#xff0c;记录了HTTP接口调用的记录&#xff0c;还有级联给上级平台&#xff0c;上级平…

Ant Design Vue中 a-table 嵌套子表格

需求&#xff1a;在父表格中嵌套子表格&#xff0c;当点击展开某一行时&#xff0c;有展开的关闭当前展开行。使用a-table中的expandedRowKeys 属性和expand 方法。链接&#xff1a;Ant Design Vue 一、属性说明&#xff1a; expandedRowKeys&#xff1a;这个主要是控制展开某行…

ubuntu strace命令

strace 是 Linux 系统中的一个调试工具&#xff0c;用于跟踪并记录系统调用&#xff08;system calls&#xff09;和信号&#xff08;signals&#xff09;。在 Ubuntu 中&#xff0c;strace 命令可以帮助开发者和系统管理员了解一个程序在运行时如何与操作系统内核进行交互&…