课程要点:ios
内存管理的必要性学习
OC是一门面向对象的语言,在软件运行过程当中会创造大量的对象,每建立一个对象系统就会给其分配一块内存,若是开发者不对建立的这些对象进行管理,当这个软件占用系统20兆内存时,iPhone开始发出内存警告,若是占用30兆内存时,iPhone OS会关闭应用程序。为了不这种状况咱们须要对我们建立的对象进行管理。管理方式有MRC(手动管理)、ARC(自动管理)。spa
MRC在11年之后,渐渐的被开发者所抛弃,但为何开发者还要学习这个东西呢。举个例子,就比如小时候家里的各类物品通常都是母亲进行整理,咱们基本上不多管这些事,但咱们多多少少都知道母亲整理物品的习惯,咱们须要找什么东西时,只要按照母亲的习惯去找就行。若是一点都不知道母亲整理物品的习惯,这对咱们找东西将会很麻烦。指针
在比较正规的公司,他们对项目的要求是很严格的。项目作完他们会对你作的项目进行一个内存检测,若是太高,他们会让你进行重构,此时若是你不知道你的项目是怎么管理内存的,那不是就是抓瞎么。code
MRC对象
在WWDC2011和iOS5以前,苹果开发者一直都在使用MRC进行内存管理。blog
由于如今Xcode建立的工程默认都是由ARC管理的。因此在使用MRC以前要关闭ARC,如图所示继承
转过MRC后看代码:内存
PS:我以前已经建立过Person类,因此采用下面代码以前先在你项目里新建一个Person类开发
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { /* object-c 使用引用计数的方式管理内存。当咱们使用一个指针指向一块内存的时候,应该对这块内存作retain操做,那么引用计数加一。当咱们再也不使用这个指针指向这块内存,应该对这块内存作release操做,那么引用计数减一。这样可使引用计数值一直保持等于指向这块内存的指针数量。retainCount返回当前内存的引用计数值。当内存被开辟后,默认的引用计数为1 。 */ //产生一个新的对象,此时不用release,由于新建的对象引用为1,不须要为第一个指向这个对象的指针额外加一计数。 Person *person1 = [[Person alloc]init]; NSInteger count = [person1 retainCount]; //赋值后count等于1 NSLog(@"%ld",count); NSObject *person2 = person1; [person2 retain]; count = [person2 retainCount]; //赋值后count等于2 NSLog(@"%ld",count); //须要认识的是,不论使用object1仍是object2调用retain方法都是同样的,由于二者指向同一块内存,计数增长减小都是之内存为对象的 [person1 release],person1 = NULL; //当object2 release以后,这个对象的引用计数为0,内存被释放,同时会调用这个对象的delloc方法。delloc方法是每个类都有的隐式方法。当用这个类建立的对象的retainCount为0的时候才会调用,本身能够在.m文件中将他重写.若是此时你打印retainCount你会发现他的值依然是1,这里你们只须要记住系统内部会对咱建立的对象进行操做,才会形成这种现象。没必要深究。 [person2 release],person2 = NULL;
/* * object release 以后为何还要把对象给置空 由于对象其实就是一个指针,指针指向的是一块内存,release仅仅是把这个内存释放了,也就是说release之后系统把这块内存给回收了。但此时指针指向得仍是这块内存。这是不符合逻辑的,全部我要把指针给置空,至此才切断了这个指针与对象的全部关系。 */ } return 0; }
输出结果:
2015-11-27 17:47:32.162 Test[2333:228117] 1 2015-11-27 17:47:32.163 Test[2333:228117] 2 Program ended with exit code: 0
重写Person.m里的delloc方法
#import "Person.h" @implementation Person //这是一个隐式方法,也就是苹果在内部已经声明和实现好了,若是我想要使用直接调用即可,若是想改变里面的内容,只需在.m里面把他重写就行。 - (void)dealloc{ NSLog(@"person对象被释放"); [super dealloc]; /* * 为何须要调用父类的dealloc方法 子类的某些实例是继承自父类的。所以,咱们须要调用父类的dealloc方法,来释放父类拥有的这些对象。 PS:每个类都有一个父类,用到这个类时不可避免的会用到父类里面的东西,因此我们在子类里释放内存的时候,要记得经过[super dealloc]来释放掉我们用到的父类里面的对象。 调用的顺序通常来讲调用的顺序是,当子类的对象释放完时,而后再释放父类的所拥有的实例。 */ } @end
输出结果:
2015-11-27 18:13:32.355 Test[2403:238207] 1 2015-11-27 18:13:32.356 Test[2403:238207] 2 2015-11-27 18:13:32.356 Test[2403:238207] person对象被释放 Program ended with exit code: 0
自动释放池:
一、Autorelease pool
自动释放池(Autorelease pool)是OC的一种内存自动回收机制,能够将一些临时变量经过自动释放池来回收统一释放
自动释放池本事销毁的时候,池子里面全部的对象都会作一次release操做
二、autorelease
任何OC对象只要调用autorelease方法,就会把该对象放到离本身最近的自动释放池中(栈顶的释放池)。
自动释放池的使用
//ios5.0新方式
@autoreleasepool
{
//池的区域
}
//ios5.0以前的老方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
//池的区域
[pool release];
自动释放池使用技巧:
PS:已重写person.m的delloc方法,并在里面写上NSLog(@"person对象已释放");若是delloc方法执行,便会有输出。
int main(){ //在MRC中并非将ARC的代码放在池中便可以自动管理内存,每建立一个对象都有在后面加上autorelease NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init]; //不加autorelease,出池后person.m的delloc方法不会执行 Person *person = [[Person alloc]init]; [pool release]; }
此时控制台输出:
Program ended with exit code: 0
int main(){ //在MRC中并非将ARC的代码放在池中便可以自动管理内存,每建立一个对象都有在后面加上autorelease NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init]; //建立对象时在后面加上autorelease,出池后,person.m里delloc方法执行 Person *person = [[[Person alloc]init] autorelease]; [pool release]; }
此时控制台输出:
2015-11-29 14:55:02.287 Test[2757:93300] person对象被释放 Program ended with exit code: 0
以上是我的看法,如有错误欢迎指正,在学习中如有不理解欢迎骚扰 QQ:2314858225