美文网首页
iOS 的内存管理(ARC)

iOS 的内存管理(ARC)

作者: SlothYP | 来源:发表于2019-04-30 16:22 被阅读0次

    基本概念

    首先,那些对象才需要我们进行内存管理呢?

    • 任何继承了NSObject的对象需要进行内存管理
    • 而其他非对象类型(int、char、float、double、struct、enum等) 不需要进行内存管理

    这是因为

    • 继承了NSObject的对象的存储在操作系统的里边。
    • 操作系统的:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表
    • 非OC对象一般放在操作系统的里面
    • 操作系统的:由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出)
    • 示例
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            int a = 10; // 栈
            int b = 20; // 栈
            // p : 栈
            // Person对象(计数器==1) : 堆
            Person *p = [[Person alloc] init];
        }
        // 经过上面代码后, 栈里面的变量a、b、p 都会被回收
        // 但是堆里面的Person对象还会留在内存中,因为它是计数器依然是1
        return 0;
    }
    

    ARC

    使用ARC后,系统会检测出何时需要保持对象,何时需要自动释放对象,何时需要释放对象,编译器会管理好对象的内存,会在何时的地方插入retain, release和autorelease,通过生成正确的代码去自动释放或者保持对象。我们完全不用担心编译器会出错

    1. ARC的判断原则

    ARC判断一个对象是否需要释放不是通过引用计数来进行判断的,而是通过强指针来进行判断的。那么什么是强指针?

    • 强指针
      • 默认所有对象的指针变量都是强指针
      • 被__strong修饰的指针
     Person *p1 = [[Person alloc] init];
     __strong  Person *p2 = [[Person alloc] init];
    
    • 弱指针
      • 被__weak修饰的指针
    __weak  Person *p = [[Person alloc] init];
    

    ARC如何通过强指针来判断?

    • 只要还有一个强指针变量指向对象,对象就会保持在内存中

    2. ARC的使用

    int main(int argc, const char * argv[]) {
        // 不用写release, main函数执行完毕后p会被自动释放
        Person *p = [[Person alloc] init];
    
        return 0;
    }
    

    3. ARC的注意点

    • 不允许调用对象的 release方法
    • 不允许调用 autorelease方法
    • 重写父类的dealloc方法时,不能再调用 [super dealloc];

    4.ARC 下单对象内存管理

    • 局部变量释放对象随之释放
    int main(int argc, const char * argv[]) {
       @autoreleasepool {
            Person *p = [[Person alloc] init];
        } // 执行到这一行局部变量p释放
        // 由于没有强指针指向对象, 所以对象也释放
        return 0;
    }
    
    • 清空指针对象随之被释放
    int main(int argc, const char * argv[]) {
       @autoreleasepool {
            Person *p = [[Person alloc] init];
            p = nil; // 执行到这一行, 由于没有强指针指向对象, 所以对象被释放
        }
        return 0;
    }
    
    • 默认所有指针都是强指针
    int main(int argc, const char * argv[]) {
       @autoreleasepool {
            // p1和p2都是强指针
            Person *p1 = [[Person alloc] init];
            __strong Person *p2 = [[Person alloc] init];
        }
        return 0;
    }
    
    • 弱指针需要明确说明
      • 注意: 千万不要使用弱指针保存新创建的对象
    int main(int argc, const char * argv[]) {
       @autoreleasepool {
            // p是弱指针, 对象会被立即释放
            __weak Person *p1 = [[Person alloc] init];
        }
        return 0;
    }
    

    5. ARC下多对象内存管理

    • ARC和MRC一样, 想拥有某个对象必须用强指针保存对象, 但是不需要在dealloc方法中release
    @interface Person : NSObject
    // MRC写法
    //@property (nonatomic, retain) Dog *dog;
    
    // ARC写法
    @property (nonatomic, strong) Dog *dog;
    @end
    

    6. ARC下循环引用问题

    • ARC和MRC一样,如果A拥有B,B也拥有A,那么必须一方使用弱指针
    @interface Person : NSObject
    @property (nonatomic, strong) Dog *dog;
    @end
    
    @interface Dog : NSObject
    // 错误写法, 循环引用会导致内存泄露
    //@property (nonatomic, strong) Person *owner;
    
    // 正确写法, 当如果保存对象建议使用weak
    @property (nonatomic, weak) Person *owner;
    @end
    

    参考自简书

    相关文章

      网友评论

          本文标题:iOS 的内存管理(ARC)

          本文链接:https://www.haomeiwen.com/subject/vgpvnqtx.html