本专题围绕 iOS 内存管理 展开,从 Apple 官方文档、WWDC、技术博客与工程实践出发,系统介绍内存分区、引用计数、MRC、ARC、自动释放池、weak 与循环引用、Category 与关联对象、Block 内存管理、深浅拷贝、以及实践与调优。同一主题按「总纲 → 内存分区 → … → Block 内存管理 → 深浅拷贝」拆成多篇,便于按需阅读与查阅。
一、核心概念简介:MRC、ARC、自动释放池
MRC(Manual Reference Counting,手动引用计数)
- 是什么:由开发者手写
retain、release、autorelease来增减对象引用计数的内存管理方式;对象引用计数为 0 时被销毁。 - 特点:遵循「谁让引用计数 +1,谁就要在合适时机 -1」的配对原则;灵活但易出错(漏 release 导致泄漏、多 release 或误用已释放对象导致野指针)。
- 何时用:iOS 5 之前为主流;当前新工程普遍用 ARC,仅少数遗留或特殊场景仍开 MRC。
- 详见:03-引用计数与MRC详解。
ARC(Automatic Reference Counting,自动引用计数)
- 是什么:编译器在编译期根据代码与所有权修饰符,自动插入 retain/release/autorelease 等调用;底层仍是引用计数,只是不再手写。
- 特点:开发者通过 strong / weak / unowned 等表达「谁持有对象」;仍需理解循环引用并用 weak 打破。
- 何时用:iOS 5+ 起推荐,当前 Objective-C 与 Swift 新项目的默认方式;Swift 仅支持 ARC。
- 详见:04-ARC详解。
自动释放池(AutoreleasePool)
- 是什么:用于延迟释放的机制:对象调用
autorelease后不立刻 -1,而是加入当前自动释放池,由池在某一时刻(如 RunLoop 迭代结束、或显式@autoreleasepool {}的})统一对池内对象发送 release。 - 特点:主线程 RunLoop 每次循环会 push/pop 一次顶层池,因此主线程上 autorelease 对象多在「本次事件处理结束」时被批量释放;子线程若无 RunLoop 需显式
@autoreleasepool控制释放时机。 - 何时用:循环中大量创建临时对象、子线程中大量 autorelease 对象时,可用
@autoreleasepool { }控制峰值与释放时机。 - 详见:05-AutoreleasePool与RunLoop。
三者关系小结
| 概念 | 与引用计数的关系 | 与自动释放池的关系 |
|---|---|---|
| MRC | 手写 retain/release,autorelease 将对象交给池 | 需理解 autorelease 与池的 drain 时机 |
| ARC | 编译器自动插入 retain/release,语义同 MRC | 编译器在需要时插入 autorelease,池的机制不变 |
| 自动释放池 | 接收 autorelease 对象,在 pop 时对它们 release | 与 MRC/ARC 共用同一套池(RunLoop 或 @autoreleasepool) |
Category 与关联对象
- 是什么:Category 不能添加实例变量,若要在分类中「挂载」数据,需用运行时的 关联对象(
objc_setAssociatedObject/objc_getAssociatedObject)。关联的 value 的持有方式由 关联策略(policy) 决定:RETAIN/COPY 表示强引用或拷贝持有,ASSIGN 表示不持有(注意野指针与循环引用)。 - 特点:主对象 dealloc 时,运行时会自动按 policy 释放所有关联的 value,一般无需在 dealloc 里手动移除。
- 何时用:为系统类或已有类通过 Category 添加「存储型属性」、或为任意对象挂扩展数据时;需正确选择 policy 并避免循环引用。
- 详见:09-Category与关联对象内存管理。
Block 内存管理
- 是什么:Block 是 OC 的闭包,可捕获变量、作为对象参与引用计数;在内存上分为 全局 Block(无捕获)、栈 Block(捕获自动变量)、堆 Block(copy 到堆),并会对捕获的 OC 对象产生强引用。
- 特点:栈 Block 需 copy 到堆才能跨作用域安全使用(ARC 下多数场景自动 copy);Block 强引用 self 且 self 强引用 Block 会循环引用,需用 __weak self 打破。
- 何时用:使用 Block/闭包作为属性、回调、异步任务时,需注意 copy 语义与循环引用;属性用 copy/strong,捕获 self 时用 weak。
- 详见:10-Block内存管理。
深浅拷贝与内存
- 是什么:浅拷贝只复制当前层,得到新对象但内部元素仍指向原对象(引用计数 +1,共享子对象);深拷贝递归复制整棵对象树,拷贝与原对象完全独立,占用新内存。
- 特点:Foundation 的
copy/mutableCopy对集合多为浅拷贝(新容器、元素共享);属性copy在 setter 里对传入值做 copy,与 Block/NSString 常用;深拷贝需自定义或initWithArray:copyItems:YES等单层深拷贝。 - 何时用:需要「多一份引用但可共享内容」用浅拷贝;需要「完全独立、避免被外部修改」用深拷贝,注意内存与性能。
- 详见:11-深浅拷贝与内存。
Option 与内存优化技术
- Option 位运算共用内存:用 NS_OPTIONS / 位域 / OptionSet 将多个布尔或选项压进一个整数,通过位运算读写,节省内存;适合 UI 状态、权限、配置等。
- 内存极限管理:在低内存、后台等场景下通过缓存上限、didReceiveMemoryWarning、按需加载等控制占用。
- Copy-on-Write(COW):值类型(如 Swift Array)在未修改前共享 buffer,写时才复制,兼顾值语义与内存/性能。
- Tagged Pointer:64 位下将小对象(如小 NSNumber、短 NSString)编码进指针本身,无堆分配、无引用计数,极省内存与开销。
- 详见:12-Option与内存优化技术。
二、专题知识全景(思维导图)
mindmap
root((iOS 内存管理))
内存分区
栈 堆 全局 常量 代码
地址与分配时机
内存对齐
结构体对齐 padding
size 与 stride
引用计数
retain release
MRC 配对原则
ARC
强引用 弱引用
编译期插入
自动释放池
AutoreleasePoolPage
RunLoop 与释放时机
weak 与循环引用
SideTable weak_table
打破循环 NSProxy Timer
实践
内存警告 Instrument
泄漏分析 音视频 图层
Category 与关联对象
关联策略 policy
释放时机 循环引用
Block 内存管理
全局 栈 堆 Block
捕获 copy 循环引用
深浅拷贝
浅拷贝 深拷贝
引用计数 共享与独立
Option 与内存优化
Option 位运算 共用内存
内存极限管理 COW Tagged Pointer
三、文档列表与阅读顺序
| 序号 | 文档 | 内容概要 | ||
|---|---|---|---|---|
| 00 | 本文(索引) | 专题结构、知识全景、文档列表与阅读顺序 | ||
| 01 | [01-主题 | 内存管理@iOS-内存五大分区](01-主题 | 内存管理@iOS-内存五大分区.md) | 栈、堆、全局区、常量区、代码区的定义、地址特征、验证与栈帧 |
| 02 | [02-主题 | 内存管理@iOS-总纲与知识体系](02-主题 | 内存管理@iOS-总纲与知识体系.md) | 内存管理目标、历史演进(MRC→ARC)、知识体系图与选型指引 |
| 03 | [03-主题 | 内存管理@iOS-引用计数与MRC详解](03-主题 | 内存管理@iOS-引用计数与MRC详解.md) | 引用计数原理、MRC 规则、retain/release/autorelease、配对原则与伪代码 |
| 04 | [04-主题 | 内存管理@iOS-ARC详解](04-主题 | 内存管理@iOS-ARC详解.md) | ARC 机制、strong/weak/unowned、所有权修饰符、与 MRC 的对比 |
| 05 | [05-主题 | 内存管理@iOS-AutoreleasePool与RunLoop](05-主题 | 内存管理@iOS-AutoreleasePool与RunLoop.md) | 自动释放池原理、AutoreleasePoolPage、与 RunLoop 的协作与释放时机 |
| 06 | [06-主题 | 内存管理@iOS-weak与循环引用](06-主题 | 内存管理@iOS-weak与循环引用.md) | weak 实现、SideTable/weak_table、循环引用破除、NSProxy 与 Timer 管理、block 注意点 |
| 07 | [07-主题 | 内存管理@iOS-实践与常见问题](07-主题 | 内存管理@iOS-实践与常见问题.md) | 内存警告、内存泄漏分析(堆快照/VM/引用链)、Timer 管理、野指针、音视频与图层场景、最佳实践 |
| 08 | [08-主题 | 内存管理@iOS-内存对齐](08-主题 | 内存管理@iOS-内存对齐.md) | 内存对齐概念、结构体对齐规则与 padding、iOS/ARM64 约定、Swift MemoryLayout、与五大分区的关系 |
| 09 | [09-主题 | 内存管理@iOS-Category与关联对象内存管理](09-主题 | 内存管理@iOS-Category与关联对象内存管理.md) | Category 与内存、关联对象 API、关联策略(RETAIN/COPY/ASSIGN)、释放时机、循环引用与最佳实践 |
| 10 | [10-主题 | 内存管理@iOS-Block内存管理](10-主题 | 内存管理@iOS-Block内存管理.md) | Block 三种类型(全局/栈/堆)、捕获与引用、copy 语义、MRC/ARC 差异、循环引用与 weak self、Swift 闭包 |
| 11 | [11-主题 | 内存管理@iOS-深浅拷贝与内存](11-主题 | 内存管理@iOS-深浅拷贝与内存.md) | 浅拷贝与深拷贝定义、Foundation copy/mutableCopy、NSCopying、属性 copy、内存与选型、Swift 值类型与写时拷贝 |
| 12 | [12-主题 | 内存管理@iOS-Option与内存优化技术](12-主题 | 内存管理@iOS-Option与内存优化技术.md) | Option 位运算共用内存(NS_OPTIONS/位域案例)、内存极限管理、Copy-on-Write、Tagged Pointer |
建议阅读顺序:先读 02 总纲 建立演进与体系,再读 01 内存五大分区 理解布局;08 内存对齐 可与 01 配合理解数据在栈/堆中的布局;然后按 03 → 04 掌握引用计数与 ARC;05、06 深入自动释放池与 weak;07 做实践与排错;09 在需要为 Category 添加「属性」或使用关联对象时阅读,注意关联策略与循环引用;10 在使用 Block/闭包作为属性或回调时阅读,理解三种 Block 类型、copy 与循环引用;11 在需要区分容器/对象「共享」与「独立副本」、或实现自定义 copy 时阅读,理解深浅拷贝与内存关系;12 了解 Option 位运算共用内存、内存极限管理、Copy-on-Write 与 Tagged Pointer 时阅读。
四、参考文献与权威来源
- Apple:About Memory Management、Transitioning to ARC Release Notes、Swift ARC
- 延伸:各分篇文末附有该篇相关参考文献与链接。