【iOS】didReceiveMemoryWarning实例方法

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时又回到第一步

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营day14|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

二叉树的递归遍历 首先需要明确的一点是,前序中序和后序在二叉树的递归遍历中的区别仅在于递归函数中操作的顺序,前序是在遍历一个节点的左右子树前进行操作,中序是在遍历一个节点的左子树后进行操作再遍历右子树,而后序是在遍历…

3D点云焊缝提取 平面交线 投影

文章目录 1. 效果2. 思路3. 源码 1. 效果 2. 思路 计算点云法向量;计算点云位姿Pose;翻转Pose中的Z轴方向,使其一致;通过Pose的Z轴对点云进行方向过滤;对点云聚类;根据目标点云的高度提取目标点云;提取两块…

云计算-Amazon S3

亚马逊S3(Amazon S3) 亚马逊S3是一种云对象存储设施。我们将使用的对象将是您在个人计算机上常用的文件。亚马逊S3产品旨在可扩展到实际无限数量的对象和无限大小的对象,但我们在本实验室的练习中只会使用少量对象。当存储许多对象时&#xf…

微服务架构下的‘黑带’安全大师:Spring Cloud Security全攻略!

深入探讨了微服务间的安全通信、安全策略设计以及面对经典安全问题的应对策略。无论你是微服务的新手还是资深开发者,都能在本文中找到提升安全功力的秘籍。让我们一起成为微服务架构下的‘黑带’安全大师! 文章目录 1. 引言微服务安全挑战与重要性Sprin…

前后端 | 低代码平台之 Erupt

前文提要 最近大家是不是都有那种危机感,项目变多了,工时压紧了,老板说,我不管你加不加班,我只看结果,项目经理说,我不管你用什么技术栈,我只要没BUG,测试说&#xff0c…

【SQL学习进阶】从入门到高级应用(一)

文章目录 MySQL命令行基本命令数据库表的概述初始化测试数据熟悉测试数据 🌈你好呀!我是 山顶风景独好 💝欢迎来到我的博客,很高兴能够在这里和您见面! 💝希望您在这里可以感受到一份轻松愉快的氛围&#x…

算法002:复写零

力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/duplicate-zeros/ 使用 双指针 来解题: 具体思路 如果是和00…

【Linux】线程安全及锁的使用

文章目录 前言一、锁1.定义一个锁变量2.pthread_mutex_init3.pthread_mutex_destroy4.pthread_mutex_lock/pthread_mutex_unlock5.静态变量锁和全局变量锁的初始化 二、问题描述及锁的运用三、RAII风格的锁 前言 临界资源: 在多个线程或进程间共享的资源. 临界区: 代码中访问临…

echarts-象形柱图

象形柱图 一般的柱图都是纯色柱图,使用象形柱图可以给柱图定义自己的样式。 样式的调节与柱图一样,核心在于symbol调节柱图的组成。 let options {tooltip: {},xAxis: {type: "category",data: ["d1", "d2", "d3&qu…

【CTF Web】NSSCTF 3868 [LitCTF 2023]这是什么?SQL !注一下 !Writeup(SQL注入+报错注入+括号闭合+DIOS)

[LitCTF 2023]这是什么?SQL !注一下 ! 为了安全起见多带了几个套罢了o(▽)q 出题人 探姬 解法 先试试这个: )))))) or 11 -- 有结果了,但是这个 flag 是假的。 flag 可能在其他表里。用 hackbar 上 DIOS payload。 …

git教程(IDEA + 命令行)

首先假设你已经安装 git 且 已经初始化完成: // 初始化git config --global user.name "你的用户名" git config --global user.email "你的邮箱"在当前文件夹下创建一个仓库,且该文件夹下会有多个项目 首先在当前文件夹下新建git…

python--pycharm中将venv删除后怎么办

在终端中输入以下命令来创建一个新的虚拟环境(可选): python -m venv venv 激活虚拟环境: Windows: .\venv\Scripts\activate选择自己项目的虚拟环境

网络故障排除—NAT-源进源出

多网络双出口一边是运营商A,一边是运营商B,将内网服务器分别映射到运营商B和运营商A出口。查了保证内部上网用户网速快管理员开启了运营商选路功能,运营商B的网站从运营商B出去,然后写有两条等价默认路由分别指向两个外网出口。营商A的网站从…

Angular(1):使用Angular CLI创建空项目

要创建一个空的 Angular 项目,可以使用 Angular CLI(命令行界面)。以下是使用 Angular CLI 创建一个新项目的步骤: 1、安装 Angular CLI: 打开你的命令行界面(在 Windows 上是 CMD、PowerShell 或 Git Bas…

渲染管线——应用阶段

知识必备——CPU和GPU 应用阶段都做了什么 应用阶段为渲染准备了什么 1.把不可见的数据剔除 2.准备好模型相关数据(顶点、法线、切线、贴图、着色器等等) 3.将数据加载到显存中 4.设置渲染状态(设置网格需要使用哪个着色器、材质、光源属性等…

区间类贪心,蓝桥云课 打折

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 0打折 - 蓝桥云课 (lanqiao.cn) 二、解题报告 1、思路分析 思路很简单&am…

回答篇二:测试开发高频面试题目

引用之前文章:测试开发高频面试题目 本篇文章是回答篇(持续更新中) 1. 在测试开发中使用哪些自动化测试工具和框架?介绍一下你对其中一个工具或框架的经验。 a. 测试中经常是用的自动化测试工具和框架有Selenium、Pytest、Postman…

“盲人独立生活技能提升方案”:科技点亮希望之光

在追求平等与包容的社会进程中,盲人群体的独立生活能力提升成为了重要议题。随着科技的飞速发展,一款名为“蝙蝠避障”的辅助软件应运而生,以其独特的实时避障和拍照识别功能,为盲人在旅行乃至日常生活中开辟了新的可能。这不仅是…

OS复习笔记ch7-1

存储的基本管理需求 重定位 重定位(Relocation):需要解决可执行文件中地址(指令和数据)和内存地址的对应。 一般有两种比较常见的重定位方式: 静态重定位(static relocation):当程序被装入内存时,一次性…

刷代码随想录有感(81):贪心算法——分发饼干

题干&#xff1a; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int index s.size() - 1;int res 0;for(int i g.size() - 1; i > 0; i--){if(index >…