美文网首页
iOS 管理内存的方式 - 用户态接口层面

iOS 管理内存的方式 - 用户态接口层面

作者: iOS小童 | 来源:发表于2019-12-05 13:37 被阅读0次

内存消耗:内存消耗指的是RAM(随机存取存储器),应用中的内存消耗分为栈大小和堆大小。ROM(Read-Only Memory)即只读内存,是一种只能读出事先所存数据的固态半导体存储器

  • 栈大小:

    1. 可被递归调用的最大方法数:每个方法都有自己的栈桢,并会消耗整体的栈空间。
    2. 一个方法中最多可以使用的变量个数:所有的变量都会载入方法的栈桢中,并消耗栈空间。
    3. 视图层级中可以嵌入的最大视图深度:如果视图层级过深,可能会导致栈溢出。
  • 堆大小:

    1. 每个进程的所有线程公用同一个堆,应用并不能控制分配给它的堆,只有操作系统才能管理堆。
    2. 使用NSString、载入图片、创建和使用JSON数据、使用视图都会消耗大量的堆内存。
    3. 类可能包含一些实例变量(int,char),但因为对象是在堆内创建的,所以它们只消耗堆内存。
    4. 当对象被赋值时,数据可能会从栈复制到堆,或值在内部使用时,它们可能会从堆复制到栈。
  1. 自动释放池块:他能确保在块内创建的对象在块完成时被回收,尽早的释放其中的对象,从而使内存用量保持在较低的水平。AppKit和UIKit框架将事件-循环的迭代放入了autoreleasepool块中,所以自动释放池块无处不在。但在一些特定的情况下,还需要创建autoreleasepool块:
  • 当你有一个创建了很多临时对象的循环时。
  • 当你创建一个自定义线程时,必须创建autoreleasepool。
  1. ARC规则
  • 不能实现或者调用retain、release、autorelease、retainCount方法。
  • 可以实现dealloc方法,不能调用。
  • 不能调用NSAllocateObject和NSDeallocateObject方法。
  • 不能再c语言的结构体内使用对象指针。
  • 不能再id类型和void类型 *类型之间自动转换
  • 不能使用NSAutorelaesepool,要用autoreleasePool块。
  • 不能使用NSZone内存区域。
  1. 引用类型
  • 强引用:指向的内存不会被释放,应用计数加1,从而扩展对象的生命周期。
  • 弱引用:不会增加引用计数,从而不会扩展对象的生命周期。
  • 软引用:和弱引用相似,只是没有弱引用那么迫切的抛弃它所引用的对象,一般还能再坚持一会。
  • 幽灵引用:最弱的引用类型,会被最早的回收清理。
  1. 变量、属性限定符
  • strong:强引用,(浅拷贝) + 1,引用期间不会被回收。用于(对象、NSMutable...)。

  • weak:弱引用,+ 0,对象会立即释放,置nil。用于(Delegate)。

  • unsafe_unretained:与weak类似,只是不会被置nil,+ 1,对象会立即释放,但不会置nil。

  • autoreleasing:由引用使用id * 传递的消息参数,+ 1,对象会立即释放。

  • asign:只进行值复制而没有任何实质性的检查,用于(BOOl、NSInter、NSUInter等)。

  • copy:深拷贝,用于(NSString、NS...、Block)。

    weak和assign:weak只能修饰对象,不能修饰基本数据类型。而assign既可以修饰基本数据类型,也可以修饰对象。但一般用于修饰基本数据类型。因为当你用assgin修饰对象时候,如果你修饰的对象销毁,该指针的指向地址仍然存在。所以造成野指针。而这个野指针的内存在堆上,所以容易造成堆内存崩溃。而基本数据类型则存在于栈上,栈上内存系统会自动处理,不会造成野指针

    atomic和nonatomic:nonatomic是非原子性,就是可以多线程访问,效率高。而atomic,是原子性的,属于安全级别的,同一个时刻只能有同一个线程访问,具有对资源的独占性,当然,效率低。atomic会在线程中加一个锁,但并不是绝对安全的。

    copy和strong:copy修饰的都是不可变对象,copy拷贝的值为深拷贝,指针和对象拷贝一份新的,strong拷贝为浅拷贝,指针拷贝。修饰string对象时无差别

    __strong和__weak 我们一般不属于强引用某个对象的时候,可以使用__weak进行修饰,典型的例子就是代理,防止循环引用。在block内部,仅用__weak所修饰的对象,如果被释放,那么这个对象在Block执行的过程中就会变成nil,这就可能会带来一些问题,比如,数组,字典的插入,而__strong在Block内部修饰的对象,会保证,在使用这个对象在scope内,这个对象都不会被释放,出了scope就会释放。

  1. 循环引用

    常出现的循环引用:

  • 委托:delegate
  • 代理:block
  • 线程与计时器

避免循环引用:

  • 对象不应该持有它的父对象,应用weak引用指向它的父对象。
  • 作为必然的结果,一个层级体系中的字对象应该保留祖先对象。
  • 连接对象不应该持有他们的目标对象。
  • 使用专用的销毁方法中断循环引用。
  1. 观察者
  • 键-值观察:addObserver:forKeyPath:options:context:方法在任何NSObject子类的对象上添加观察者,得到通知。
  • 通知中心:一个对象可以注册为通知中心(NSNotificationCenter)对象的观察者,并接收NSNotification对象。
  1. 对象寿命与泄漏

尽量尽可能地避免出现长寿命的对象,也要不必每次都浪费时间来创建它们。所以合理使用单例和全局变量。

单例应该满足(避免使用,会增加启动时间):

  • 队列操作(如日志和埋点)
  • 访问共享资源(如缓存)
  • 资源池(如线程池或链接池)

全局变量必须满足:(少使用,占内存)

  • 没有被其他对象锁持有
  • 不是常量
  • 整个应用中只有一个。

避免以上问题,合理应用属性去减少内存的消耗,降低平均和峰值内存。

相关文章

  • iOS 管理内存的方式 - 用户态接口层面

    内存消耗:内存消耗指的是RAM(随机存取存储器),应用中的内存消耗分为栈大小和堆大小。ROM(Read-Only ...

  • 用户态内存管理

    linux内核态的内存管理主要是基于伙伴系统和slab机制,而用户态内存管理主要是VMA虚拟地址空间。 在linu...

  • Linux进程内存管理(一)

    本文主要讲用户态进程的内存管理,而不是内核的内存管理。简单地说,就是和 malloc 和 free 相关的内存管理...

  • iOS内存管理

    iOS内存管理机制 基本数据类型无需我们管理,内存管理的范围是对象,iOS内存管理采用了引用计数器的方式来管理内存...

  • 内存管理:不看白不看,看了就是赚

    一、iOS的内存管理方式 1、小对象的内存管理 -- Tagged Pointer 2、普通对象的内存管理 -- ...

  • runloop 总结篇

    用户态 和内核态1.是以权限划分,用户态不直接对如何分配内存等等进行管理,怕出各种情况等等。用户态需要切换成内核...

  • 新支付接口

    用户管理相关接口 用户登录 接口说明:用户登录 接口地址:/api/user/login 请求方式:POST co...

  • 微内核 seL4 Untyped

    seL4的内存管理 在seL4中,除了少量静态内存属于内核,所有的物理内存都由用户态管理。在root task开始...

  • ABI与API

    ABIapplication binary interface二进制层面的接口规定:内存布局,函数调用方式,符号修...

  • 用户栈和内核栈

    为了区分程序的运行级别,有用户态和核心态之分,也叫目态和管态。硬件驱动、CPU和内存管理等底层操作和进程管理、诊断...

网友评论

      本文标题:iOS 管理内存的方式 - 用户态接口层面

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