内存问题

  • app中内存激增

    可能的原因是:读入大量图像的同时改变其尺寸(比如循环压缩),图像文件读入到NSData对象,从中生成UIImage对象,改变对象尺寸后生成新的UIImage对象

  • ARC规则

    ARC有效时,对象类型上必须附加所有权修饰符。所有权修饰符一共有4种:

    • __strong 修饰符
    • __weak 修饰符
    • __unsafe_unretained 修饰符
    • __autoreleasing 修饰符
    • __strong 修饰符

  • strong修饰符是id类型和对象类型默认的所有权修饰符。id和对象类型在没有明确指定所有权修饰符时,,默认为strong。例如,下面两段代码是相同的效果:

    id obj = [[NSObject alloc] init];
    id __strong obj = [[NSObject alloc] init];
    

    __strong修饰符表示对对象的强引用。持有强引用的变量在超出其作用域时被废弃,随着强引用的失效,引用的对象会随之释放。

    {
    //自己生成并持有对象
    id strong obj = [[NSObject alloc] init];
    } // 因为变量obj超出其作用域,强引用失效,所以自动释放自己持有的对象,对象的所有者不存在,因此废弃该对象
    

    当然,不仅仅适用于自己生成并持有的对象,非自己生成并持有的对象也适用,附有strong修饰符的变量可以相互赋值,在赋值上也能够正确的管理其对象的所有者。 通过strong修饰符,不必要再次键入retain和release,完美的满足了“内存管理的思考方式”。

  • weak 修饰符 看起来通过strong修饰符就能完美地进行内存管理,但是实际上,仅用strong就可能会出现引用计数式内存管理中存在的“循环引用”问题。weak 修饰符就是为了解决循环引用的问题,weak 修饰符与strong相反,提供弱引用。弱引用不能持有对象实例。

    {
    //自己生成并持有对象
    id 
    strong obj0 = [[NSObject alloc] init]; //obj0为强引用,所以自己持有对象
    id __weak obj1 = obj0; //obj1变量持有生成对象的弱引用
    } // 因为变量obj0超出其作用域,强引用失效,所以自动释放自己持有的对象,对象的所有者不存在,因此废弃该对象
    

    __weak修饰符还有一个优点,在持有某对象的弱引用时,若该对象被废弃,则此弱引用将自动失效且处于nil被赋值的状态。

  • __unsafe_unretained 修饰符 unsafe_unretained 修饰符,正如其名,是不安全的所有权修饰符。尽管ARC式的内存管理是编译器的工作,但附有unsafe_unretained 修饰符的变量不属于编译器的内存管理对象。

    id unsafe_unretained obj1 = nil;
    {
      id strong obj0 = [[NSObject alloc] init]; //obj0为强引用,所以自己持有对象
      obj1 = obj0; //虽然obj0变量赋值给obj1,但是obj1变量既不持有对象的强引用也不持有弱引用
      NSLog(@"A: %@",obj1); //输出obj1变量表示的对象
    }//因为obj0变量超出其作用域,强引用失效,所以自动释放自己持有的对象,因为对象无持有者,所以废弃该对象
    NSLog(@"B: %@",obj1); //输出obj1变量表示的对象 obj1变量表示的对象已经被废弃(悬垂指针),错误访问
    

    在使用unsafe_unretained修饰符时,赋值给附有strong修饰符的变量必须确保被赋值的对象却是存在。在iOS4 以后,苹果开始用weak替代了unsafe_unretained。

  • __autoreleasing 修饰符 虽然ARC不能直接使用autorelease,但实际上,ARC有效时autorelease功能是其起作用的。

    ARC无效的时候用法如下:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id  obj = [[NSObject alloc] init];
    [obj autorelease];
    [pool drain];
    

    ARC有效的时候用法就改成下面这样了:

    @autoreleasepool {
    id __autoreleasing obj = [[NSObject alloc] init];
    }
    

    指定@autoreleasepool快来代替NSAutoreleasePool类对象生成、持有以及废弃。 NSRunLoop等实现不论ARC有效还是无效,均能够随时释放注册到autorelease中的对象。

  • ARC有效下的一些规则:

    • 不能使用retain、release、retain、ratainCount、autorelease
    • 不能使用NSAllocateObject/NSDeallocateObject
    • 必须遵守内存管理的方法命名规则
    • 不要显示调用dealloc
    • 使用@autoreleasepool代替NSAutoreleasePool
    • 不能使用区域(NSZone)
    • 对象型变量不能作为C语言结构体的成员
    • 显示转换id和void
    • id型或对象型变量赋值给void 或者逆向赋值都需要进行特定的转换,如果只想单纯的赋值,则可以使用”__bridge 转换“。

results matching ""

    No results matching ""