【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

 

posted @ 2017-03-01 11:35  专注·精彩  阅读(464)  评论(0编辑  收藏  举报