zoukankan      html  css  js  c++  java
  • 【Objective-C 篇】 ☞ 4. 内存管理

    内存管理 : 

    主要对堆内存进行管理,所谓的管理是指内存的分配(创建)和释放(回收)

    内存管理:管理对象的分配和释放,回收那些不需要再使用的对象(内存)

     

    下列行为都会增加一个app的内存占用

    • 创建一个OC对象
    • 定义一个变量
    • 调用一个函数或者方法

    如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验

    1.1 两种管理方式

    MRC(Manual Reference Counting):手动引用计数(手动管理内存)

    所有对象的内都需要我们手动管理, 需要程序员自己编写retain/release等代码

    ARC(Automatic Reference Counting):自动引用计数(自动管理内存)

    不需要程序员管理内存,编译器会在适当的地方自动给我们添加retain/release等代码

    注意点: OC中的ARCjava中的垃圾回收机制不太一样,java中的垃圾回收是系统干得,OC中的ARC是编译器干得

    1.2 引用计数器(Reference Counting)

    • 每个对象都有自己的引用计数器,引用计数器是用来计算对象被引用的次数。
    • 发送消息时(alloccopynew),将引用计数器置为1
    • OC语言使用对象的引用计数来管理内存。一个对象只要有另一个对象指向它,引用计数就得+1,当另一个对象不指向它时,引用计数就-1,当引用计数减成0时,说明这个对象已经没有人用了,系统会将对象的内存空间释放掉。

     

    MRC是指对象的引用计数的加减操作手动进行,意思就是由程序员写代码来完成。

    ARC是指对象的引用计数的加减操作自动进行,意思是说不需要程序员写代码,而是由编译器自动生成代码完成。

    1.3 MRC下的引用计数器的操作

    1)引用计数器加1retain

    当你需要使用一个别人创建好的对象时,为了防止在使用此对象期间别人释放了这个对象,我们要将此对象的引用计数器加1(程序员通知引用计数器),只要给对象发送retain消息,引用计数器就会加1

    2)引用计数器减1release

    • 当你使用的对象不再使用时,发送release消息
    • release消息将对象的引用计数器减1
    • 如果引用计数器为0,则释放对象所占的存储空间。

    3dealloc与对象销毁

    • 当对象的引用计数器为0时,说明已经没有任何引用指向对象,对象就会被系统自动销毁。
    • 系统销毁对象之前,会自动向对象发送一条消息”dealloc”消息,对象所占的空间就会被释放,千万不要自己去调用dealloc消息。
    • 可以使用“retainCount消息”,查看当期引用计数器的值。

    NSLog(@“引用.retainCount = %ld”, 引用.retainCount); //打印引用计数器的值

    1.4 dealloc方法

    当一个对象的引用计数器值为0时(对象即将被销毁时),系统就会自动调用dealloc方法。

    因此,从dealloc方法有没有被调用,就可以判断出对象是否被销毁

    一般通过dealloc方法来监听一个对象有没有被释放,而不用retainCount方法(retainCount方法有时候不是很准确)

     

    • dealloc方法的重写
      • 一般会重写dealloc方法,在这里释放相关资源,dealloc就是对象的遗言
      • 一旦重写了dealloc方法,就必须要在最后面调用 [super dealloc]  (ARC下,不能调用父类的方法dealloc)

     

    • 使用注意
      • 不能手动调用dealloc方法,由系统自动调用
      • 一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)

     

    1.5 野指针与空指针:

    僵尸对象:已经被销毁的对象(不能在使用的对象)

    野指针

    • 指向僵尸对象(不可用内存)的指针
    • 给野指针发消息会报EXC_BAD_ACCESS错误

    空指针:

    • 没有指向存储空间的指针(里面存的是nil,也就是0)
    • 给空指针发消息是没有任何反应的
    • 为了避免野指针错误的常见办法。在对象被销毁之后,将指向对象的指针变为空指针。

        

    只要一个对象被释放了,我们就称这个对象为"僵尸对象"

    当一个指针指向一个僵尸对象,我们就称这个指针为野指针只要给一个野指针发送消息就会报错

         

         

      监听"僵尸对象"的报错(方便调试,会在控制台输出错因):

         

    注意:null.name[null run]; 不能用null去访问属性和调用方法。虽然不会报错,但是什么也不会发生。

    OC是弱语法语言,有些错误编译不会报错!

     

    1.6 内存管理原则

    苹果官方规定的内存管理原则:

    1. 谁创建谁release:

    如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease

    1. retain谁release:

    只要你调用了retain,就必须调用一次release

    总结:

    • 有加就有减
    • 曾经让对象的计数器+1,就必须在最后让计数器-1

     

     

    1.7 MRC项目与ARC项目之间的转换

    创建的项目默认使用ARC

    • ARC > MRC

    如果要使用MRC,要么将某个需要使用MRC.m文件设置成MRC,或将整个项目变成MRC

    1) 如何将单个.m文件设置成MRC/ARC

    Xcode中选中项目-Build Phases-Compile Sources-》选中需要使用MRC.m文件-》双击此文件。

    在弹出地小窗口中输入以下内容:

    -fno-objc-arc  (设置MRC:表示文件不支持Objective-CARC)

    -fobjc-arc  (设置ARC:表示文件支持Objective-CARC)

    2) 如何将整个项目改成MRC

    Xcode中选中项目==>Build Settings==>搜索"Automatic Reference ( ARC ) ”==>找到"Objective-C Automatic Reference Counting"将其值"YES"改成NO. 意思是关闭ARC,此时项目就全是MRC

    • MRC  —> ARC:

        Xcode菜单:Edit —>Convert —> To Objective-C ARC…

      

      如何让代码既兼容ARC又兼容MRC?

    //MRC

    #if(!__has_feature(objc_arc))

        //MRC下的执行代码

    #endif

    //ARC

    #if __has_feature(objc_arc)

        //ARC下的执行代码

    #else

        //MRC下的执行代码

    #endif

  • 相关阅读:
    多线程中的静态代理模式
    ARP报文
    静态链表代码
    顺序表中的思路
    数据结构与算法
    我是见鬼了吗?这是史上最邪恶的脚本!没有之一
    细说"回车"和"换行"的故事
    SVN版本控制系统搭建(结合http服务)
    cooike和session到底是个啥
    Python3中 if __name__=='__main__'是个什么意思
  • 原文地址:https://www.cnblogs.com/bossren/p/6428133.html
Copyright © 2011-2022 走看看