iOS内存管理
作者:
39Coding | 来源:发表于
2020-06-30 14:50 被阅读0次
使用CADisplayLink、NSTimer有什么注意点?
- 注意内存泄漏、循环引用的问题(self弱引用
timer
会造成内存泄漏,强引用timer
会造成循环引用)
- 使用
NSProxy
作为timer
的target
,然后弱引用self
,打破循环引用的问题
-
NSProxy
效率比NSObject
高,专门用来做消息转发的,会省略以下步骤:
1. 去父类寻找方法(本来NSProxy
自身也没其他方法了)
2. 动态方法解析阶段
3. 消息转发的第一步forwardingTargetForSelector
- 最后直接来到消息转发的第二步,执行
methodSignatureForSelector
有返回值再执行forwardInvocation
介绍下内存的几大区域讲一下
- 低地址
- 保留:其他用途,大小由平台决定(32位、64位)
- 代码段(
__TEXT
):编译之后的代码,例如函数
- 数据段(
__DATA
):常量区,比如全局变量、静态变量
- 字符串常量:例如
NSString *str = @"123";
(直接写出来的,不是通过方法创建的那种字符串)
- 已初始化数据:例如
static int a = 10;
(定义就赋值的)
- 未初始化数据:例如
static int b;
(没赋值的)
- 堆
heap
:通过alloc
、malloc
、calloc
等动态分配的空间(实例对象),分配的内存空间地址【越来越大】
- 栈
stack
:函数调用开销,比如局部变量,分配的内存空间地址【越来越小】(先进后出)
- 内核区:系统内核相关的区域,只能系统访问,例如让线程休眠的操作
- 高地址

iOS程序的内存布局.jpg
你对 iOS 内存管理的理解
- 使用引用计数来管理OC对象的内存
- 一个新创建的
OC
对象引用计数默认是1,当引用计数减为0,OC
对象就会销毁,释放其占用的内存空间
- 调用
retain
会让OC
对象的引用计数+1,调用release
会让OC
对象的引用计数-1
- 内存管理的经验总结:
- 当调用
alloc
、new
、copy
、mutableCopy
方法返回了一个对象,在不需要这个对象时,要调用release
或者autorelease
来释放它
- 想拥有某个对象,就让它的引用计数+1;不想再拥有某个对象,就让它的引用计数-1

引用计数和weak引用的存储.jpg
ARC 都帮我们做了什么?
-
ARC
是LLVM编译器
和Runtime系统
相互协助的一个结果
- LLVM
:例如在某个作用域的{}即将结束的时候,自动对里面的对象调用release方法
- Runtime
:例如weak
指针的实现,在程序运行的过程中,监控到对象要销毁时会去清空对象的弱引用
weak指针的实现原理
-
weak
指针会将弱引用存储到一个哈希表(SideTable->weak_table)里面,当对象要销毁时取出这个哈希表,把里面存储的弱引用都清除掉
- 对象调用
dealloc
时会判断isa
的weakly_referenced
是否被弱引用过,有的话会调用clearDeallocating
函数,根据当前对象的地址值通过哈希查找,找到对应的弱引用表,清除里面存储的弱引用

copy和mutableCopy.jpg
autorelease对象在什么时机会被调用release
- 如果是自定义的
autoreleasepool
,会在自动释放池的{}结束前一刻调用release
- 如果不是在自定义的
autoreleasepool
,而是在main
函数的autoreleasepool
,是由RunLoop
控制的,可能是在某次RunLoop
循环中,在RunLoop
休眠之前调用了release
(kCFRunLoopBeforeWaiting
)

autorelease时机(验证).jpg

autorelease时机(原理).jpg

AutoreleasePoolPage的结构.jpg

dealloc的底层实现流程.jpg
方法里有局部对象, 出了方法后会立即释放吗
-
MRC
环境下不会,会等RunLoop
那次循环的休眠之前才释放
-
ARC
环境下会,LLVM
会在方法的{}即将结束的时候,自动对里面的对象调用release
方法
本文标题:iOS内存管理
本文链接:https://www.haomeiwen.com/subject/lmlxqktx.html
网友评论