2010年4月22日星期四

iPhone开发中内存的合理使用(转)

iPhone 开发过程中,内存的使用至关重要。不但要合理分配使用内存,还要注意内存泄露的问题, 因为内存泄露会导致程序由于内存不足而崩溃。根据个人开发的经验来看,在开发iPhone程序的过程中,关于内存的问题需要注意以下几点:

  1. 内存分配、释放成对出现
    使用 alloc 分配的内存对象需要在用完后 调用release释放

  2. 注意copy,retain,assign操作符的区别
    copy, retain操作符赋值的对象和alloc一样,需要release释放,否则会导致内存泄露
    assign 操作符的含义是将对象指向另一对象, 两者指向的是同一内存对象,无需调用release释放 

  3. NSArray, NSDictionary, NSMutableArray, NSMutableDictionary等容器类, 在使用这些容器类的时候要注意, 在添加对象到这些类对象时,容器类会自动调用一次retain,比如
    NSString* string  = [[NSString alloc] initWithString:@”test string”];  // refCount = 1
    NSArray* array = [NSArray array];
    [array addObject:string]; // refCount = 2
    [string release]; // refCount = 1
    这种情况, 即便string已经调用release,但是在加入 array中时已经调用了一次retain,注意refCount的变化 简单介绍一下iPhone 或者说Objective C对对象的管理机制。 OC中采用一种引用计数refCount的方式来管理内存对象,当refCount等于0的时候就会释放对象所占的内存, 操作符alloc,copy, retain都会将refCount加1表示引用计数增加, 而调用release使 refCount自动减1, 当refCount=0时表示该对象已经没有被引用,可以将其释放, 之后该对象便不可用

  4. 连续重复分配内存的过程最好创建自己的自动释放池 NSAutoreleasePool,通常是在for、while等循环操作过程中,比如
    for( int i=0; i < 100; i++ )
    {
    NSString* str = [[NSString alloc] initWithString:@”some string”];
    // 针对str的操作
    [str release];
    }
    在这种情况下,有2点需要注意,首先如果可能,就把str的分配、释放放在for循环外面, 从而减少内存的分配、释放导致程序效率低下,也利于内存回收,如上例应该为
    NSString* str = [[NSString alloc] initWithString:@”some string”];
    for( int i=0; i < 100; i++ )
    {
    // 针对str的操作
    }
    [str release];
    如果实际情况复杂,不能像例子中那样抽离出循环外,需要创建自己的内存管理池, 同样适用于需要大量autorelease对象的过程
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    for(int i=0; i < 100; i++ )
    {
    // actions
    }
    [pool release];
    之所以要这样做,是因为apple处理iPhone的内存管理机制问题, 通常情况下,系统会在需要的时候释放整理所有的autorelease对象,这就是为什么有时候autorelease对象在作用域范围外还有可能是有效的

  5. 避免不常用对象驻留内存, 桌面开发的tx很多喜欢在程序初始化的时候将某些资源比如小图片加载进内存,从而提高程序运行效率。 但这种方式在iPhone以及其它mobile移动设备开发时需要避免,因为对于这些设备来说,内存永远显得不足(当然普通pc内存也是越大越好:) )。 按照apple的官方说法, Load resources lazily . 就是在需要的时候再从硬盘上读取,而避免常驻内存。


原文链接:http://www.flyblog.info/catprogramming/168.html
发表评论