iOS进阶- 内存管理
一、 请聊一聊iOS的内存管理?
通用内存基本原理:
内存管理简单来说有两类,即指令存储、数据存储; 更详细的说分为5类: 代码段存储、数据段存储(初始化过了的全局变量、静态变量、常量)、BSD区(存储没有被初始化的数据)、堆区(存储对象、手段管理)、栈区(存储基本类型数据和局部变量,系统管理)。由于其他存储区域都是固定或者是有系统帮我们管理,所以iOS主要注重的对堆区的管理。
image.png
iOS内存管理计数: 引入计数 ,程序的runloop每次执行过程都会对对象的引用计数进行收集,对于等于零的对象,系统会将它放入自动释放池等待释放。当我们执行alloc/new/copy/mutilCopy时 对象被持有引用,引用计数默认是1,当对它进行retain操作时,对象的引用计数为加1,当对一个对象执行release操作时,对象的引用计数减一。 它存讯的原则谁引用谁释放,retain和release成堆出现。不然内存就会出问题。
image
管理类型分两种: MRC(手动管理)和ARC(不需要显示处理对象的引用计数,ARC这种编译机制会在编译的时候在合适的地方加入retain和release ),虽然ARC 不需要显示的调用retain和release 但是也响应的除了很多问题,比如: 野指针(指针指向的地址提前释放,导致没有找到)、空指针(调用指针时,指针被其他线程提前复制了nill或者0) 、循环引用(由于相互的引用,彼此都不执行release 操作,引用计数一直不会为0,导致彼此的内存都回收不了)
出现循环引用的场景以及解决方法:
场景1: 定时器
原因: 当前对象强持有定时器,定时器内部强持有了当前对象,通过当前打断点当前类的dealloc 方法一直没有走
解决方法时,一种是在界面周期函数viewDidDisappear 中调用当前函数的invalidate函数释放定时器。
场景2: 代理
原因:对象B强持有协议P1,对象A强持有对象B,并A又强持有了协议P1。
解决方法时,解决方法通常是 B对象在设置协议属性时使用weak内存修饰符区修饰。
场景三: block
原因:对象B强持有block blockOne,对象A强持有对象B,blockOne又强持有了对象A。
解决方法时,在blockOne改成对A对象进行弱引用,通常用 __weak typeOf(obj) weakObj = obj;
二、聊一下自动释放池
工作原理: 对于添加到自动释放池的对象,当它除了临时作用域并不会直接被销毁,而是添加到了最近一次的自动释放池里,当自动释放池执行drain函数即销毁的时候,自动释放池会想池子里每一个对象发送一个release 消息。