------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一. 原理1.对于任何继承了NSObject的对象,都有一个与之关联的整形变量,称为引用计数器;只有计数器的值为0的时候,OC就回收该对象,否则永不回收。
2.当使用release方法释放时,计数器的值减1
3. 当使用retain方法时,计数器的值加1
4. 当对象被回收时候,自动调用对象的dealloc方法
5. 使用retainCount方法来获取引用计数器的值
6. autorelease pool
6.1 autorelease pool ,需要手动创立。autorelease pool 的真名是 NSAutoreleasePool。NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
6.2 NSAutoreleasePool 内部包含一个数组(NSMutableArray),用来保存声 明为 autorelease 的所有对象。如果一个对象声明为 autorelease,系统所做的 工作就是把这个对象加入到这个数组中去。
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain coun t = 1,把此对象加入 autorelease pool 中
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain coun t = 1,把此对象加入 autorelease pool 中
6.3 NSAutoreleasePool 自身在销毁的时候,会遍历一遍这个数组,release 数组中的每个成员。如果此时数组中成员的 retain count 为 1,那么 release 之后,retain count 为 0,对象正式被销毁。如果此时数组中成员的 retain count 大于 1,那么 release 之后,retain count 大于 0,此对象依然没有被销毁, 内存泄露。
6.4 默认只有一个 autorelease pool,通常类似于下面这个例子。
{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
// do something
[pool release];
return 0;
}
{
@autoreleasePool{
//do something
}
return 0;
}
所有标记为 autorelease 的对象都只有在这个 pool 销毁时才被销毁。如果 你有大量的对象标记为 autorelease,这显然不能很好的利用内存.(自己网上查资料看到的一道面试题)
int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i, j;
for (i = 0; i < 100; i )
{
for (j = 0; j < 100000; j )
[NSString stringWithFormat:@"1234567890"];//产生的对象是 autorelease 的。
}
[pool release];
return (0);
}
7. Objective-C 程序中可以嵌套创建多个 autorelease pool。在需要大量创 建局部变量的时候,可以创建内嵌的 autorelease pool 来及时释放内存
int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i, j;
for (i = 0; i < 100; i )
{
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
for (j = 0; j < 100000; j )
[NSString stringWithFormat:@"1234567890"];//产生的对象是 autorele ase 的。
[loopPool release];
}
[pool release];
return (0);
}
二. 口诀
1 谁创建,谁释放(类似于“谁污染,谁治理”)。如果通过 alloc、new 或 copy 来创建一个对象,那么必须调用 release 或 autorelease。换句话说, 不是你创建的,就不用你去释放。
例如,你在一个函数中 alloc 生成了一个对象,且这个对象只在这个函数中 被使用,那么你必须在这个函数中调用 release 或 autorelease。如果在一个 class 的某个方法中 alloc 一个成员对象,且没有调用 autorelease,那么需要在这个类的 dealloc 方法中调用 release;如果调用了 autorelease,那么在 dealloc 方法中什么都不需要做。
2 除了 alloc、new 或 copy 之外的方法创建的对象都被声明了 autorelease。
3 谁 retain,谁 release。只要你调用了 retain,无论这个对象是如何生成的,你都要调用 release。