iOS 内存管理总结

来源:互联网 发布:手机淘宝怎么晒图 编辑:程序博客网 时间:2024/06/11 05:06
http://www.apple.com.cn/developer/iphone/library/documentation/UserExperience/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

更多中文官方文档 http://www.apple.com.cn/developer/mac/library/navigation/ios.html

一、自动释放池


自动释放池,任何标记为自动释放并因此添加到池中的对象,将在池本身被释放的同时也自动释放,程序可以有多个自动释放池,它们还可以是嵌套的。

如果程序在运行时将产生大量的临时对象,就可能需要在程序中创建多重自动释放池。例如:

    for (int i = 0; i < 1000000; i++) {        NSString *string = [NSString stringWithString:@"ABC"];        string = [string lowercaseString];        string = [string stringByAppendingString:@"XYZ"];        NSLog(@"%@",string);    }

在执行此段代码的时候会有大量的临时对象产生,如果就这样一直循环下去,就会存在内存泄露的问题(内存泄露是不再使用的内存没有得到释放,致使我们不能再对次块内存进行使用)。因为这些临时对象会在不断的分配空间直到执行此循环操作的runloop的本次循环结束才会去释放。所以我们只需要稍微做一些修改,添加一个自动释放池,每次循环完了就会去释放在池中的自动释放的对象

    for (int i = 0; i < 1000000; i++) {        @autoreleasepool {            NSString *string = [NSString stringWithString:@"ABC"];            string = [string lowercaseString];            string = [string stringByAppendingString:@"XYZ"];            NSLog(@"%@",string);        }    }

自动释放池并不包含实际的对象本身,仅仅是对池释放的时候要释放的对象的引用,通过像当前的自动释放池发送一条autorelease消息,就可以将一个对象添加到其中,以便以后释放。

Cocoa应用程序中的每个线程都会维护一个自己的NSAutoreleasePool对象的堆栈。当一个线程终止时, 它会自动地释放所有与自身相关的自动释放池。在基于Application Kit的应用程序中,自动释放池会在程序的主线程中被自动创建和销毁,所以,您的代码通常无需处理它们。但是,如果您在Application Kit的主线程之外发起Cocoa调用,则您需要创建自己的自动释放池。如果您正在编写一个Foundation应用程序,或者如果您拆分了一个线程,则是属于这种情况。

如果您的应用程序或线程是长期存在的,并且会潜在地生成大量的自动释放对象,那么您应该定期地销毁和创建自动释放池(像 Application Kit在主线程中所做的那样),否则,自动释放对象会产生堆积且您的内存占用量也会增长。如果被拆分的线程不会发起Cocoa调用,那么您无需创建自动释 放池。

二、引用计数

内存中常量字符串的空间分配与其他对象不同,他们没有引用计数的机制,包括使用常量字符串初始化的不可变字符串对象也是没有引用计数机制的。

在声明为retain的属性setter里面要注意:

- (void)setNumTest:(NSNumber *)numTest1{    [numTest1 retain];    [numTest release];    numTest = numTest1;}


- (void)setNumTest:(NSNumber *)numTest1{    [numTest release];    [numTest1 retain];    numTest = numTest1;}

这两者之间是有区别的。比如参数和属性指向的是同一个地址,那么下面这种就会去对已经释放掉的内存块进行操作。

其实

- (void)setNumTest:(NSNumber *)numTest1{    if(numTest != numTest1){        [numTest1 retain];        [numTest release];        numTest = numTest1;    }}

这样书写会更保险一点,个人觉得如果先判断一下上面两种写法就是一样的了。