浅谈iOS内存管理机制
iOS内存管理机制的原理是引用计数,引用计数简单来说就是统计一块内存的所有权,当这块内存被创建出来的时候,它的引用计数从0增加到1,表示有一个对象或指针持有这块内存,拥有这块内存的所有权,如果这时候有另外一个对象或指针指向这块内存,那么为了表示这个后来的对象或指针对这块内存的所有权,引用计数加1变为2,之后若有一个对象或指针不再指向这块内存时,引用计数减1,表示这个对象或指针不再拥有这块内存的所有权,当一块内存的引用计数变为0,表示没有任何对象或指针持有这块内存,系统便会立刻释放掉这块内存。
其中在开发时引用计数又分为ARC(自动内存管理)和MRC(手动内存管理)。ARC的本质其实就是MRC,只不过是系统帮助开发者管理已创建的对象或内存空间,自动在系统认为合适的时间和地点释放掉已经失去作用的内存空间,原理是一样的。虽然ARC操作起来很方便,不但减少了代码量,而且降低了内存出错的概率,但因为ARC不一定会及时释放,所以程序有时候可能会占用内存较大。而MRC若做得好,通过手动管理,及时释放掉不需要的内存空间,便可保证程序长时间运行在良好状态上。
在MRC中会引起引用计数变化的关键字有:alloc,retain,copy,release,autorelease。(strong关键字只用于ARC,作用等同于retain)
alloc:当一个类的对象创建,需要开辟内存空间的时候,会使用alloc,alloc是一个类方法,只能用类调用,它的作用是开辟一块新的内存空间,并使这块内存的引用计数从0增加到1,注意,是新的内存空间,每次用类alloc出来的都是一块新的内存空间,与上一次alloc出来的内存空间没有必然联系,而且上一次alloc出来的内存空间仍然存在,不会被释放。
retain:retain是一个实例方法,只能由对象调用,它的作用是使这个对象的内存空间的引用计数加1,并不会新开辟一块内存空间,通常于赋值是调用,如:
对象2=[对象1 retain];表示对象2同样拥有这块内存的所有权。若只是简单地赋值,如:对象2=对象1;那么当对象1的内存空间被释放的时候,对象2便会成为野指针,再对对象2进行操作便会造成内存错误。
copy:copy同样是一个实例方法,只能由对象调用,返回一个新的对象,它的作用是复制一个对象到一块新的内存空间上,旧内存空间的引用计数不会变化,新的内存空间的引用计数从0增加到1,也就是说,虽然内容一样,但实质上是两块内存,相当于克隆,一个变成两个。其中copy又分为浅拷贝、深拷贝和真正的深拷贝,浅拷贝只是拷贝地址与retain等同;深拷贝是拷贝内容,会新开辟新内存,与retain不一样;真正的深拷贝是对于容器类来说的,如数组类、字典类和集合类(包括可变和不可变),假设有一个数组类对象,普通的深拷贝会开辟一块新内存存放这个对象,但这个数组对象里面的各个元素的地址却没有改变也就是说数组元素只是进行了retain或者浅拷贝而已,并没有创建新的内存空间,而真正的深拷贝,不但数组对象本身进行了深拷贝,连数组元素都进行了深拷贝,即为各个数组元素开辟了新的内存空间。
release:release是一个实例方法,同样只能由对象调用,它的作用是使对象的内存空间的引用计数减1,若引用计数变为0则系统会立刻释放掉这块内存。如果引用计数为0的基础上再调用release,便会造成过度释放,使内存崩溃;
autorelease:autorelease是一个实例方法,同样只能由对象调用,它的作用于release类似,但不是立刻减1,相当于一个延迟的release,通常用于方法返回值的释放,如便利构造器。autorelease会在程序走出自动释放池时执行,通常系统会自动生成自动释放池(即使是MRC下),也可以自己设定自动释放池,如:
@autoreleasepool{
obj= [[NSObject alloc]init];
[obj autorelease];
}
当程序走出“}”时obj的引用计数就会减1.
除了以上所述的关键字,还有一些方法会引起引用计数的变化,如UI中父视图添加、移除子视图,导航控制器或视图控制器推出新的视图控制器以及返回,容器类(数组、字典和集合)添加和移除元素。
当子视图添加到父视图上时,子视图的引用计数加1,移除时引用计数减1,若父视图引用计数变为0内存被释放,其所有的子视图都会被release一次,即引用计数减1,原则上只有这三种情况子视图的引用计数会发生变化,其他如父视图引用计数的加减都不会影响到子视图。
容器类的情况与视图类似,添加元素,该元素引用计数加1,移除元素,该元素引用计数减1,容器引用计数变为0所占用内存被释放,容器所有元素release,引用计数减1,其他情况下容器本身的引用计数变化不会影响到容器内元素的引用计数变化。
导航控制器或视图控制器推出新的视图控制器会使被推出的视图控制器的引用计数加1,该视图控制器返回的时候引用计数减1,具体方法如下:
导航控制器推出视图控制器调用方法:- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
返回时同样用导航控制器调用方法:- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
视图控制器推出视图控制器调用方法:- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
返回时被推出的视图控制器调用方法:- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion
应注意:当一个对象的引用计数变为0占用内存被释放时,会调用- (void)dealloc方法,所以如果在MRC下自定义类,必须在该方法里将该类中属性关键字设置为retain或copy的属性release一次,以免造成内存泄露,重写方法不要忘记在第一行添加[super dealloc];。
浅谈iOS内存管理机制的更多相关文章
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
- 【转载】浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在 ...
- iOS内存管理机制解析之MRC手动引用计数机制
前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...
- 浅谈OC内存管理
一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空 ...
- 浅谈Android内存管理
最近在网上看了不少Android内存管理方面的博文,但是文章大多都是就单个方面去介绍内存管理,没有能全局把握,缺乏系统性阐述,而且有些观点有误,仅仅知道这些,还是无法从整体上理解内存管理,对培养系统优 ...
- iOS 内存管理机制和循环引用处理方法
简述 ARC: 自动引用计数, Automatic Reference Counting MRC: Mannul Reference Counting ARC工作原理 1.当每次创建一个新实例时,AR ...
- iOS 内存管理-copy、 retain、 assign 、readonly 、 readwrite、nonatomic、@property、@synthesize、@dynamic、IB_DESIGNABLE 、 IBInspectable、IBOutletCollection
浅谈iOS内存管理机制 alloc,retain,copy,release,autorelease 1)使用@property配合@synthesize可以让编译器自动实现getter/setter方 ...
- MRC、ARC内存管理机制
MRC下,oc内存管理遵循"谁创建.谁释放.谁引用.谁管理"的机制,当创建或引用一个对象时,需要向她发送alloc,copy,retain消息,当释放该对象时需要发送release ...
- 12.Object-C--浅谈OC的内存管理机制
昨天学习了OC的内存管理机制,今天想总结一下,所以接下来我要在这里bibi一下:OC的内存管理. 首先我要说的是,内存管理的作用范围. 内存管理的作用范围: 任何继承了NSObject的对象,对其他基 ...
随机推荐
- 【转】深入学习Redis(1):Redis内存模型
原文:https://www.cnblogs.com/kismetv/p/8654978.html 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Red ...
- 20155211 课下测试ch11补做
20155211 课下测试ch11补做 Web服务器的实现基于HTTP协议,有关HTTP协议,下面说法正确的是() A.可以用telnet充当Web服务器的客户端进行调试 B.HTTP请求的GET和P ...
- 20155239吕宇轩 Linux下IPC机制
20155239吕宇轩 Linux下IPC机制 - 共享内存 原理:把所有需要使用的共享数据都存放在共享内存 区域中,任何想要访问这些共享数据的进程都必须在自己的进程地址空间中新增加一块内存区域,用来 ...
- 4542: [Hnoi2016]大数
4542: [Hnoi2016]大数 链接 分析: 如果p等于2或者5,可以根据最后一位直接知道是不是p的倍数,所以直接记录一个前缀和即可. 如果p不是2或者5,那么一个区间是p的倍数,当且仅当$\f ...
- 【SoDiaoEditor电子病历编辑器更新啦】--谨以献给那些还在医疗行业奋斗的小伙伴们
为什么推荐的人这么少~~~~ 更新(2017-4-18): 截止目前已知的已有2个三甲医院在使用该编辑器,容我内心澎湃以下,O(∩_∩)O哈哈~ 先放github地址:https://gith ...
- C#用Oracle.DataAccess中连接Oracle要注意版本问题!转)
一般人,不包括全部平时在开发中使用的都是32位的PC机,所以安装的也是Oracle32位的客户端.但是一般服务器都是64位的,安装的也是 64位的Oracle客户端,如果要部署使用Oracle.Dat ...
- javaweb学习6——自定义标签
声明:本文只是自学过程中,记录自己不会的知识点的摘要,如果想详细学习JavaWeb,请到孤傲苍狼博客学习,JavaWeb学习点此跳转 本文链接:https://www.cnblogs.com/xdp- ...
- cadence allegro16.6 pcb文件转pads pcb文件方法教程
在pcb设计工作中,有时会被要求将pcb文件转成其他软件的格式,pcb Allegro装Pads的方法如下. 在转换的过程中我们需要用到三种软件,ad.pads.allegro.转换的流程是:alle ...
- 怎样注册Docker Hub账号
Docker Hub是Docker的远程镜像仓库,类似于GitHub;如果没有搭建本地私有仓库,Docker会默认去Docker Hub拉镜像. 访问Docker Hub官网https://hub.d ...
- 如何fork比特币的源码并同步更新到本地
一.首先在Github上fork比特币源码,就会在自己的项目库里创建一份比特币代码的拷贝. 打开https://github.com/bitcoin/bitcoin,点击右上角的“Fok”图标,稍 ...