美文网首页
性能之内存管理

性能之内存管理

作者: 清水一心 | 来源:发表于2017-06-03 17:05 被阅读0次

    应用中的内存消耗分为:栈大小和堆大小。

    栈大小

    • 可被递归调用的最大方法数
    • 一个方法中最多可以使用的变量个数
    • 视图层级中可以嵌入的最大视图深度

    堆大小

    每个进程的所有线程共享一个堆。一个应用可以使用的堆大小通常远远小于设备的RAM值。

    自动释放池块(autoreleasepool)

    在一些特殊情况下,需要创建自己的autoreleasepool。
    * 当你有一个创建了很多临时对象的循环时
    * 当你创建一个线程时

    ARC的规则

    * 不能实现或调用retain、release、autorelease或retainCount方法
      这一规则不仅针对对象,对选择器同样有效
    * 可以实现dealloc方法,但不能调用它包括超类
    * 不能调用NSAllocateObject和NSDeallocateObject方法
      应该使用alloc方法创建对象,运行时负责回收对象
    * 不能在C语言的结构体内使用对象指针
    * 不能在 id 类型和void * 类型之间自动转换。如果需要,必须做显示转换。
    * 不能使用NSAutoreleasepool,要替换成autoreleasepool
    * 不能使用NSZone内寸区域
    * 属性的访问器名称不能以new开头,以确保与MRC的互操作性
    * Core Foundation类型需要自己手动管理内存
    

    引用类型

    • 弱引用:不会增加引用计数
    • 强引用:会增加引用计数

    变量限定符

    • _strong、 _weak 、_unsafe_unretained、_autoreleasesing
      例子:
      Person* _strong p1 = [[Person alloc] init]// 引用计数为1,并且对象在p1引用期间不会被回收
      Person* _weak p2 = [[Person alloc] init]// 引用计数为0,对象会被立即释放,且p2将被设置为nil
      Person* _unsafe_unretained p3 = [[Person alloc] init]// 引用计数为1,对象会被立即释放,且p3不会被设置为nil
      Person*_autoreleasing p4 = [[Person alloc] init]// 引用计数为1,当方法返回时对象会被立即释放

    属性限定符

    这个就不在此做解释了,不懂的,百度上有很多教程
    

    僵尸对象

    用来捕捉内存错误的调试功能
    通常情况下,当引用计数为0时,对象会立即释放,会使得调试困难。开启僵尸对象,那么对象不会立即释放内存,而是标记为僵尸。
    NSZombieEnabled是一个环境变量,可以控制Core Foundation的运行时是否将使用僵尸对象
    注意:在发布构建时一定要禁用

    内存管理规则

    * 你拥有所有自己创建的对象,如new、alloc、copy、mutableCopy
    * 你可以用MRC中的retain或ARC中的__strong引用来拥有任何对象的持有关系
    * 一定不能抛弃原本并不存在持有关系的对象
    

    循环引用

    主要出现的场景委托、块、线程与计时器

    观察者

    • 键-值观察
      它不会维持观察对象、被观察对象以及上下文对象的强引用。如有必要,你需要自行维护对它们的强引用。
    • 通知中心
      一个对象可以注册为通知中心的观察者,并接收NSNotification对象。它不会对观察者持有强引用。

    返回错误

    当某个方法接收NSError**参数,并在发生错误时填充错误变量,则必须使用__autoreleasing限定符。

    弱类型:id

    在使用常规命名的方式时,应避免使用id。尽量使用具体的类取而代之。

    合理使用全局变量与单例

    推荐做法

      避免大量的单例
      对子对象使用__strong
      对父对象使用__weak
      对使引用图闭合的对象(如委托)使用__weak
      对数值属性,使用assign
      对块属性,使用copy限定符
      当声明使用NSError**参数的方法时,需要使用__autoreleasing。并注意用正确的语法: NSError*__autoreleasing *。
      避免在块内直接引用外部的变量。在外用weakify,在内strongify
      销毁计时器、移除观察者、解除回调(例如:委托设置为nil)
    

    扩展

    依赖注入(Typhoon和Objection框架)
    Instruments进行内存分析

    相关文章

      网友评论

          本文标题:性能之内存管理

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