objc内存管理
一、内存管理规则
1、对于通过调用带有alloc、copy、mutableCopy、new或者create一词的方法创建的任何对象及其内存,你都拥有所有权。你负责在之后的某个时刻向该对象发送release消息来释放资源。使用类似[[Foo alloc]init...]命令创建的对象需要释放。任何使用类似[foo copy]方法创建的对象需要释放。任何和CreateFoo()类似的调用所返回的对象也需要释放。
2、对于通过不带上述词的方法调用获得的对象,你都没有所有权。这些对象可以再当前执行栈中任意调用,离开当前栈之后,这些对象就不可用了。
说明:从技术上说,对象如果之前没有被保留, 那么在下一个运行循环后会被释放。不过从遵循内存管理规则的角度考虑,你可以假定对象出了作用域后,只要没有被保留,就会被释放。
通过其他方法调用的对象通常是“自动释放”对象,自动释放对象会在应用程序下次离开运行循环时被释放。
二、使用自动释放举例:
1、返回一个自动释放对象
-(Foo *)getFoo
{
Foo *foo = [[Foo alloc]init];
//对foo执行一些操作
return [foo autorelease];
}
2、alloc/autorelease对象
-(void)someMethod
{
Foo *foo = [[[Foo alloc]init]autorelease];
//在这里foo仍然有效
//在方法退出之前不会释放
[foo dosomething];
}
三、使用自动释放可能耗尽内存
在自动释放池中留有大量对象
-(void)inflateMemoryUsage
{
for(NSUInteger n = 0; n<100000; ++n)
{
//对象是自动释放的
NSData *data = [self getBigBlockOfData];
//对数据进行处理
[self doStuff:data];
}
//在这里100000个数据对象都还有效
}
解决方法:
1、在循环中释放对象
-(void)inflateMemoryUsage
{
for(NSUInteger n=0; n < 100000; ++n)
{
//保留计数是1
NSData *data = [[NSData alloc]init];
[self putBlobOfDataIntoData:data];
//使用创建的对象
//处理数据
[self doStuff:data];
[data release];//对象在这里被释放
}
//没有遗留任何东西
}
2、在必须使用很多自动释放对象的情况下,在循环内部创建一个自动释放池,在使用完代码中的对象后,清空自动释放池并释放对象。
-(void)inflateMemoryUsage
{
for(NSUInteger n = 0; n<100000; ++n)
{
//对象是自动释放的
NSData *data = [self getBigBlockOfData];
//对数据进行处理
[self doStuff:data];
}
//在这里100000个数据对象都还有效
}
解决方法:
1、在循环中释放对象
-(void)inflateMemoryUsage
{
for(NSUInteger n=0; n < 100000; ++n)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//该对象是自动释放的
NSData *data = [self getBigBlobOfData];
//对data进行些处理
[self doStuff:data];
[pool release];//自动释放对象在这里释放,使用drain或release
}
//没有遗留任何对象
}
自动释放池中自动释放对象被推入到可用的最高层的自动释放池,这点和嵌套栈有些类似。所以如果在一个自动释放池内创建多个池,在清空池子时只有最里面的自动释放池内的自动释放对象被释放。