浅谈iOS内存管理机制

时间:2022-09-30 20:45:32

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内存管理机制的更多相关文章

  1. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  2. 【转载】浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在 ...

  3. iOS内存管理机制解析之MRC手动引用计数机制

    前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...

  4. 浅谈OC内存管理

    一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空 ...

  5. 浅谈Android内存管理

    最近在网上看了不少Android内存管理方面的博文,但是文章大多都是就单个方面去介绍内存管理,没有能全局把握,缺乏系统性阐述,而且有些观点有误,仅仅知道这些,还是无法从整体上理解内存管理,对培养系统优 ...

  6. iOS 内存管理机制和循环引用处理方法

    简述 ARC: 自动引用计数, Automatic Reference Counting MRC: Mannul Reference Counting ARC工作原理 1.当每次创建一个新实例时,AR ...

  7. 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方 ...

  8. MRC、ARC内存管理机制

    MRC下,oc内存管理遵循"谁创建.谁释放.谁引用.谁管理"的机制,当创建或引用一个对象时,需要向她发送alloc,copy,retain消息,当释放该对象时需要发送release ...

  9. 12.Object-C--浅谈OC的内存管理机制

    昨天学习了OC的内存管理机制,今天想总结一下,所以接下来我要在这里bibi一下:OC的内存管理. 首先我要说的是,内存管理的作用范围. 内存管理的作用范围: 任何继承了NSObject的对象,对其他基 ...

随机推荐

  1. 手把手教你 用 wpf 制作metro ProgressRing (Windows8 等待动画)

    效果图: 还在羡慕metro的ProgressRing吗? wpf 也可以拥有 首先说下思路, 一共6个点围绕一直圆转,所以需要使用rotation动画 并且一直转下去. 那么下面的问题就好解决了. ...

  2. C++的辅助工具介绍 [转]

    C++的辅助工具介绍 1 文档类  (1) Doxygen  参考站点:http://www.doxygen.org  Doxygen是一种适合C风格语言(如C++.C.IDL.Java甚至包括C#和 ...

  3. boost库区间range基本原理及使用实例

    由 www.169it.com 搜集整理 区间的概念类似于STL中的容器概念.一个区间提供了可以访问半开放区间[first,one_past_last)中元素的迭代器,还提供了区间中的元素数量的信息. ...

  4. JAVA入门[15]-过滤器filter

    一.过滤器 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的: 在客户端的请求访问后端资源之前,拦截这些请求. 在服务器的响应发送回客户端之前,处理这些响应. 参考:http:/ ...

  5. pypi上传问题

    pypi上传过程中报错403 windows 解决办法: 1.建一个新的记事本编辑内容 [distutils]index-servers = pypi [pypi]repository:https:/ ...

  6. append、appendTo、prepend、prependTo、before、insertBefore、after、insertAfter、replaceAll方法被调用后,原本在页面上显示的元素会消失

    详细描述: $ele.append..appendTo..prepend..prependTo..before..insertBefore..after..insertAfter..replaceAl ...

  7. 上任com的发布流程

    参考:https://blog.csdn.net/qq_19674905/article/details/80268815 首先把本地代码提交到远程自己的git分支,然后merge request到m ...

  8. solr高亮设置以及摘要

    高亮显示 public SolrDocumentList query(String str) { SolrQuery query = new SolrQuery(str); //设置高亮,以下两种方式 ...

  9. Class.forName和ClassLoader.loadClass的比较【转载】

    Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4.Clas ...

  10. 事务(Transaction)概念和特性

    http://baike.baidu.com/view/121511.htm 概念 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库 ...