美文网首页IOS开发基础(oc)
ios开发基础学习笔记(十四)--ARC

ios开发基础学习笔记(十四)--ARC

作者: miloluo | 来源:发表于2018-06-26 21:03 被阅读0次

    前言

    大家好,我是milo,前面对那么多关于MRC的知识做了总结,今天终于过渡到ARC来了,其实学习就是深入浅出,懂得更多基础,能够让你在开发中都做到心中有数,不至于盲目,共勉。

    ARC简介

    ARC是ios5.0之后增加的新特性,全称Automatic Reference Counting(自动引用计数),不同于MRC手动管理内存的方式,ARC会让编译器会自动在适当的地方插入适当的retain、release、autorelease语句,也就是说不需要程序猿手动进行内存管理了。而且我们创建文件的时候默认都是使用ARC的。

    ARC的使用演示

    什么使用?根本就不需要去想它在哪好吗?它是编译器的特性,我们写代码时它会自动暗中帮我们补全的,请看下面代码示例:

    JJPerson.m里重写一下dealloc方法

    为了观察对象是否被释放重写dealloc方法.png

    (注意:可重写,不可[super dealloc],ARC的管理方式下,oc对象不能写关于内存的代码)

    main.m里写一个对象不写内存管理的代码

    int main(int argc, const char * argv[]) {
        JJPerson *person = [[JJPerson alloc] init];
        JJDog *dog = [[JJDog alloc] init];
        [person setDog:dog];
        return 0;
    }
    
    

    打印结果:

    2018-06-26 15:09:09.007235+0800 ARC[1353:78888] -[JJPerson dealloc]
    2018-06-26 15:09:09.007475+0800 ARC[1353:78888] -[JJDog dealloc]
    Program ended with exit code: 0
    

    所以在ARC下,我们不写内存管理的代码,不会引起内存问题(而且ARC也不会让你写的)。

    ARC的判断原则

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

    强指针:默认所有的指针都是强指针。只要是有强指针指向一个对象,那么这个对象就不会被释放,如果没有强指针指向一个对象,那么这个对象就被立即回收,用__strong标示,但是因为默认所有指针都是强指针,所以他没有用。

    弱指针:弱指针指向的对象不影响对象回收,用__weak标示,ARC中也存在循环引用的问题,所以弱指针常用在循环引用,当出现循环引用的时候,必须要有一端是弱指针。

    强指针:

    int main(int argc, const char * argv[]) {
        
        __strong JJPerson *person = [[JJPerson alloc] init];
    // __strong写不写都是默认__strong的,所以没有用;但__weak就不能乱用了,如果在这里代替__strong,那么刚创建的对象马上就被销毁   
        
        JJDog *dog = [[JJDog alloc] init];  
        [person setDog:dog];
        return 0;
    }
    

    强指针的使用比较简单,默认不写就行了;而弱指针则要注意以下两点。

    弱指针:
    1、出现循环依赖的时候要让一端为weak,这一点和MRC一样,只不过MRC使用的是assign
    2、刚创建的对象不能使用weak指针指向它,否则会立即释放,因为没有强指针指向它。比如我们常常会使用weak的方式创建控件,但是我们不能直接让weak指针直接指向对象,而是应该先直接创建出控件,再让指针指向它

    ARC的使用细节

    ARC中的@property
    strong : 用于OC对象, 相当于MRC中的retain
    weak : 用于OC对象, 相当于MRC中的assign
    assign : 用于基本数据类型, 跟MRC中的assign一样
    copy : 一般用于NSString, 跟MRC中的copy一样

    不能调用release、retain、autorelease、retainCount

    可以重写dealloc,但是不能调用[super dealloc]

    ARC的优点

    ARC是编译器特性,而不是运行时特性,ARC不是其它语言中的垃圾回收, 有着本质区别。

    1、完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务
    2、基本上能够避免内存泄露
    3、有时还能更加快速,因为编译器还可以执行某些优化

    ----------------------------深究部分-------------------------------

    看完前面我们就对ARC有了初步的认识了,它就是编译器偷偷摸摸并且合理地把你的对象内存释放掉了,这个合理的时机就是:

    结论:通过alloc、new、copy等方式创建出来的对象是在出了作用域后被销毁;而通过get方法、类方法等非前面所说的方式创建出来的对象都是在出了autoreleasepool后被释放的。
    (都要满足没有其他强指针指向对象)

    跟MRC很像对吧!所以说ARC就是帮我们做了MRC要做的工作并且进行了优化。

    下面代码通过打断点+重写dealloc方法就可以让我们知道对象的释放时间点

    int main(int argc, const char * argv[]) {
        
         // {}表示一个作用域
        @autoreleasepool{
            {
                JJPerson *person = [[JJPerson alloc] init];
            }//  在这行person被释放
        }
        
        @autoreleasepool{
            {
                JJPerson *newPerson = [JJPerson person];
            }
        }//  在这行newPerson被释放
        
        return 0;
    }
    

    但是作用域归作用域(包括autoreleasepool),它也满足没有强指针指向对象就释放的原则,如果依旧还是有一个强指针指向这个对象,那就算出了作用域也无法被释放,作用域的作用可以理解为对里面的指针做一次release操作

    见下面代码:

    int main(int argc, const char * argv[]) {
        
         // {}表示一个作用域
        @autoreleasepool{
            JJPerson *person1; //  定义一个在作用域外的指针
            {
                JJPerson *person = [[JJPerson alloc] init];
                person1 = person;//  让外界指针指向对象
            }//  这行对象没有释放,因为还有一个外界指针指向它
        }//  在这行对象被释放,因为外界指针出autoreleasepool这个作用域后被释放
        
        @autoreleasepool{
            {
                JJPerson *newPerson = [JJPerson person];
            }
        }//  在这行newPerson被释放
        
        return 0;
    }
    

    深究以后我们就能发现,ARC的内存释放和MRC的内存释放基本都是一样的喔!该用release和autorelease的时机跟我前面分析的MRC都一样的喔!很有意思吧!

    相关文章

      网友评论

        本文标题:ios开发基础学习笔记(十四)--ARC

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