MRC、ARC内存管理机制
MRC下,oc内存管理遵循“谁创建、谁释放、谁引用、谁管理”的机制,当创建或引用一个对象时,需要向她发送alloc,copy,retain消息,当释放该对象时需要发送release消息,当引用计数为零的时候,系统释放该对象。
ARC是自动引用计数,管理机制与手动机制一样,只是不再需要调用retain,release,autorelease,它会在适当的位置插入release和autorelease。使用ARC不代表不需要内存管理了,例如使用block时要避免循环引用,代理作为属性时,要用弱指针指引。
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];。
MRC、ARC内存管理机制的更多相关文章
- ARC内存管理机制详解
ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...
- iOS-OC的MRC和ARC内存管理机制
1. Objective-c语言中的MRC(MannulReference Counting) 在MRC的内存管理模式下,对变量的管理相关的方法有:retain,release和autorelease ...
- iOS MRC ARC 内存管理
转自:http://www.jianshu.com/p/48665652e4e4 1. 什么是内存管理 程序在运行的过程中通常通过以下行为,来增加程序的的内存占用 创建一个OC对象 定义一个变量 调用 ...
- 【iOS开发-35】有了ARC内存管理机制,是否还须要操心内存溢出等问题?——面试必备
答案:必需要操心啊,ARC也不是万能的. 这里主要是涉及到集合类的数据类型. 比方数组,我们定义了一个可变数组muarr1,然后把一个对象p1加到muarr1中,此时会对这个对象retain一次,相当 ...
- iOS内存管理机制解析之MRC手动引用计数机制
前言: iOS的内存管理机制ARC和MRC是程序猿參加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5 ...
- iOS ARC内存管理
iOS的内存管理机制,只要是iOS开发者,不管多长的时间经验,都能说出来一点,但是要深入的理解.还是不简单的.随着ARC(自动管理内存)的流行.iOS开发者告别了手动管理内存的复杂工作.但是自动管理内 ...
- OC的内存管理机制
总的来说OC有三种内存管理机制,下面将分别对这三种机制做简要的概述. 1.手动引用计数(Mannul Reference Counting-MRC) mannul:用手的,手工的. 引用计数:reta ...
- IOS中内存管理机制浅解
我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是 由系统自己管理的,放在栈上).如果一个对象创建并使用后没有得 ...
- 浅谈iOS内存管理机制
iOS内存管理机制的原理是引用计数,引用计数简单来说就是统计一块内存的所有权,当这块内存被创建出来的时候,它的引用计数从0增加到1,表示有一个对象或指针持有这块内存,拥有这块内存的所有权,如果这时候有 ...
随机推荐
- Java IO面试
1. 讲讲IO里面的常见类,字节流.字符流.接口.实现类.方法阻塞. 字节流和字符流的区别: 1)字节流处理单元为1个字节,操作字节和字节数组,而字符流处理的单元为2个字节的Unicode字符,分别操 ...
- Python dir()函数
您可以使用内置的dir()函数列出一个定义对象的标识符.例如,对于一个模块,包括在模块中定义的函数,类和变量. 当你给dir()提供一个模块名字时,它返回在那个模块中定义的名字的列表.当没有为其提供参 ...
- UVa 129 困难的串
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- iOS 设置控件圆角、文字、字体
以按钮为例: UIButton btn = [UIButton new]; btn.layer.masksToBounds = YES; btn.layer.cornerRadius = 10.0; ...
- 负载均衡探测器lbd
负载均衡探测器lbd 大型网站为了解决海量访问问题,往往采用负载均衡技术,将用户的访问分配到不同的服务器上.网站的负载均衡可以从DNS和HTTP两个环节进行实施.在进行Web渗透测试的时候,需要先 ...
- php 常用代码段
1.写文件 $fp = fopen("jsapi_ticket.json", "w+"); fwrite($fp, $str); fclose($fp); 2. ...
- RF & Microarray
REF[24] 随机森林是一个很好适用于微阵列数据的分类算法: 1.即使大多数的预测变量都是噪音,RF仍然具有优秀的性能,因此不需要对基因进行预选择. 2.能够应用于变量数远远大于观测数据量的情况 3 ...
- Angular - - Angular数据类型判断
angular.isArray 判断括号内的值是否为数组. 格式:angular.isArray(value); value: 被判断是否为数组的值. ------------------------ ...
- iOS开发之内存缓存机制
使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,是程序高效的运行.有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求. 内存缓存我们可以使用sdk中的NSURLC ...
- eclipse开发velocity实例(初学)
开发环境 Eclipse Java EE IDE for Web Developers.(Version: Helios Service Release 1) jdk1.6.0_07 ...