一、完善版思维导图(覆盖全部知识点)
mindmap
root(iOS开发知识体系)
基础语言
Objective-C / Swift
基本语法、特性对比
内存管理(ARC / MRC)
引用计数原理、自动释放池
Runtime(运行时)
isa指针、方法缓存、消息转发
Runloop(运行循环)
模式、事件源、定时器
多线程
GCD(队列、任务、信号量)
NSOperation(依赖、取消、优先级)
动态特性
KVC / KVO
Notification / Delegate / Block
界面开发
UIKit核心组件
UIView、UIViewController、UIWindow
常用控件(UILabel、UIButton、UITableView等)
Auto Layout / 布局适配
Masonry、XIB、Storyboard、Size Classes
响应链(Responder Chain)
事件传递、hitTest、手势识别
动画
UIView动画、Core Animation、关键帧动画、转场动画
数据存储与网络
数据持久化
plist、UserDefaults、SQLite、CoreData、归档
网络请求
URLSession、Alamofire、缓存策略
数据解析
JSON(Codable、JSONSerialization)、XML(XMLParser)
网络安全
HTTPS、证书校验(SSL Pinning)、AES/RSA加密
架构与设计模式
架构模式
MVC、MVVM、MVP、VIPER、Clean Architecture
设计模式
创建型(单例、工厂、建造者)
结构型(代理、适配器、外观)
行为型(观察者、策略、命令)
组件化 / 模块化
路由(URLRouter、Target-Action)
中间件(CTMediator、BeeHive)
私有库管理(CocoaPods、SPM)
设计原则
SOLID、高内聚低耦合
性能优化与调试
启动优化
pre-main耗时、动态库合并、二进制重排
卡顿监测
Runloop监听、FPS监控、耗时堆栈捕获
内存泄漏检测
MLeaksFinder、Instruments、循环引用分析
包体积优化
资源压缩、代码混淆、LinkMap分析
工具与工程化
版本控制
Git(分支策略、Rebase、Hook)
依赖管理
CocoaPods、Carthage、Swift Package Manager
持续集成/持续部署
Jenkins、GitHub Actions、GitLab CI
测试
单元测试(XCTest)、UI测试、自动化测试
底层原理
Runtime源码分析
objc_msgSend、方法缓存、关联对象
Runloop原理
CFRunloop、mach_msg、事件源
内存管理底层
Tagged Pointer、散列表、弱引用表
类的结构
isa、元类、class_rw_t、class_ro_t
推荐学习资源
数据结构与算法
《大话数据结构》《算法(第4版)》、LeetCode
网络
《图解HTTP》《TCP/IP详解 卷1》
架构与设计模式
GitHub优秀仓库、设计模式文档
iOS底层
《Objective-C高级编程》《Swift进阶》、Apple官方文档
二、面试题及答案(专业答案分层 + 通俗解释)
1. 什么是ARC?它是如何工作的?
【初级掌握】
ARC(Automatic Reference Counting)是编译器的自动引用计数机制,用于管理 Objective-C 对象的内存。它在编译时自动插入 retain / release / autorelease 方法,减少内存泄漏和野指针的风险。
【中级扩展】
ARC 通过跟踪对象的强引用计数来决定何时释放对象。当引用计数降为 0 时,对象被释放。ARC 还引入了弱引用(__weak),当对象被释放时弱引用自动置 nil。此外,ARC 利用自动释放池(@autoreleasepool)管理临时对象的释放时机。
【高级深入】
ARC 实际上是编译器和运行时协作的结果。编译器在合适位置插入内存管理调用,运行时提供以下支持:
- 弱引用表:维护所有弱引用,对象销毁时将其置 nil。
- 自动释放池优化:通过
objc_autoreleasePoolPush/pop实现池的边界管理。 - 关联对象的内存管理:通过
objc_setAssociatedObject的 policy 决定引用关系。 - 对 Toll-Free Bridging 的处理:需手动或通过
__bridge关键字管理 CF 对象的内存。
【通俗解释】
ARC 就像自动管家,帮你管理对象内存。当对象不再被使用时,管家会自动把它清理掉,你不需要手动写释放代码,避免内存泄漏。弱引用就像“临时通行证”,不会让对象一直活着。
2. 什么是 Runloop?有哪些应用场景?
【初级掌握】
Runloop 是一个事件处理循环,用于管理线程在无事件时休眠、有事件时处理。常见应用:定时器(NSTimer)、界面刷新、PerformSelector、保持线程存活(如 AFNetworking 常驻线程)。
【中级扩展】
Runloop 基于 mach_msg() 实现,通过用户态和内核态切换实现高效休眠。Runloop 有多个模式(Mode),如 NSDefaultRunLoopMode、UITrackingRunLoopMode,同一时间只能运行在一个模式下,可通过切换模式隔离事件。Runloop 还会在每个循环中管理自动释放池(_objc_autoreleasePoolPush/pop)。
【高级深入】
Runloop 的底层是 CFRunloop,包含以下组件:
- Runloop 对象:包含多个 Mode。
- Mode:包含 Source/Timer/Observer 集合。
- Source:分为 Source0(非 mach_port 事件)和 Source1(基于 mach_port 的内核事件)。
- Observer:监听 Runloop 状态(进入、处理事件、休眠等),用于卡顿监控、界面更新等。
可以通过 CFRunloopObserver 监听 Runloop 状态,实现卡顿监控。例如在子线程中开启 Runloop 并添加 Source,可保活线程。
【通俗解释】
Runloop 是线程的“心跳”,没事就睡觉,有事就处理,确保线程不退出并能响应事件。比如你滑动屏幕时,Runloop 会处理触摸事件,更新界面;没操作时,它就让 CPU 休息省电。
3. 什么是 Category?和 Extension 的区别?
【初级掌握】
- Category:为类添加方法(不能添加实例变量),运行时有效。
- Extension:在编译期添加属性和方法,必须要有类的源码,常用于私有属性和方法。
【中级扩展】
Category 可以分散类的实现,但同名方法会覆盖(最后编译的生效)。Extension 本质是匿名 Category,但可以添加实例变量(因为编译期确定)。Category 不能直接添加实例变量,但可以通过关联对象(Associated Object)间接实现。
【高级深入】
Category 的底层结构是 category_t,包含:
- 实例方法列表、类方法列表
- 协议列表
- 属性列表
运行时通过 objc_loadCategory 将 Category 的方法合并到类的方法列表中。合并时,Category 的方法会放在原类方法的前面,所以 Category 方法会“覆盖”原类同名方法(但实际不是覆盖,而是查找顺序问题)。关联对象通过全局哈希表维护,与对象生命周期绑定。
【通俗解释】
Category 像给现有类贴便签添加方法,比如给 NSString 添加一个反转字符串的方法。Extension 像类的小秘密,只能自己用,可以添加私有属性和方法,比如在 .m 文件中声明一个私有属性。
4. 什么是 Block?循环引用如何解决?
【初级掌握】
Block 是封装了函数及其上下文的匿名函数。解决循环引用:使用 __weak 修饰外部变量,避免强引用。
【中级扩展】
Block 有三种类型:
- 全局 Block(_NSConcreteGlobalBlock):不捕获变量,存储在数据段。
- 栈 Block(_NSConcreteStackBlock):捕获变量,存储在栈上,需要手动拷贝到堆。
- 堆 Block(_NSConcreteMallocBlock):栈 Block 拷贝到堆,或手动 copy。
循环引用常见于 Block 强引用 self,self 又持有 Block(如属性),需用 __weak + __strong(内部使用)打破。
【高级深入】
Block 底层是结构体,包含:
- isa 指针(指向类对象)
- flags、reserved
- 函数指针
- 捕获的变量(按值或按引用)
-
__block变量会包装成结构体,允许在 Block 内修改变量。
MRC 下使用 __block 可避免循环引用(需手动置 nil),ARC 下 __block 会导致强引用,推荐 __weak。在 Block 内部,如果需要在多行代码中使用弱引用,可先转为强引用(__strong)防止在执行过程中被释放。
【通俗解释】
Block 是一段可以随时执行的代码片段,类似 C 的匿名函数,但能捕获外部变量。循环引用就像两个人互相抓住对方不放,谁也松不开手。解决方法是用 __weak 让其中一人松开手(弱引用),这样两人就自由了。
5. Runtime 中消息发送的流程是怎样的?
【初级掌握】
消息发送流程:通过对象的 isa 找到类,在方法缓存、方法列表中查找,向父类递归查找,未找到则进入动态方法解析、消息转发,最后崩溃。
【中级扩展】
具体步骤:
- 通过 isa 指针找到类。
- 在类的缓存(cache_t)中查找方法(哈希查找)。
- 如果缓存未命中,在当前类的方法列表(method_array_t)中查找。
- 如果未找到,沿继承链向上查找(父类缓存、方法列表)。
- 如果最终未找到,进入动态方法解析:调用
+resolveInstanceMethod或+resolveClassMethod,可在此动态添加方法。 - 如果解析未实现,进入快速转发:调用
-forwardingTargetForSelector:,返回一个能处理该消息的对象。 - 如果快速转发返回 nil,进入完整转发:调用
-methodSignatureForSelector:获取方法签名,再通过-forwardInvocation:将消息转发给其他对象。 - 如果以上都未处理,抛出
doesNotRecognizeSelector:异常。
【高级深入】
消息发送由 objc_msgSend 实现,使用汇编优化(如 arm64 汇编)以提高性能。方法缓存采用开放式哈希表,缓存的 key 是 selector,value 是方法实现(IMP)。动态方法解析时可调用 class_addMethod。转发阶段可用于实现代理、多继承、AOP 等设计。
【通俗解释】
当调用对象方法时,Runtime 像邮递员,先找自己有没有这个方法,没有就沿着继承链向上找,再没有就进入“动态处理”流程,比如问你能不能现加一个方法,或者转发给别的对象处理,最后如果都不行就报错崩溃。
6. 如何优化 UITableView 的滑动流畅性?
【初级掌握】
避免在 cellForRow 中做耗时操作,使用重用机制(dequeueReusableCell),提前计算并缓存 cell 高度。
【中级扩展】
具体优化措施:
- 异步绘制:将文本渲染、图片解码放到子线程,减少主线程负担。
- 减少离屏渲染:避免设置圆角、阴影、mask 等触发离屏渲染的操作,可使用贝塞尔曲线绘制圆角或使用带圆角的图片。
- 减少视图层级:尽量使用 drawRect 绘制复杂内容,减少 subviews 数量。
- 预加载:在滑动即将到达时提前加载数据。
- 使用 shouldRasterize:对静态内容开启光栅化,缓存为位图,但需注意内存。
- 图片优化:使用合适尺寸的图片,异步解码(如 SDWebImage 的解码选项)。
【高级深入】
可以使用 CADisplayLink 监控帧率,检测卡顿。通过 Runloop 监听卡顿时长,记录堆栈。对于高度缓存,可使用 NSCache 或字典,并注意在数据变化时更新缓存。对于复杂 cell,可考虑使用异步绘制框架(如 AsyncDisplayKit/Texture),将绘制逻辑放到后台线程。还可以利用 UITableView 的预加载 API(prefetchDataSource)提前准备数据。
【通俗解释】
让表格滚动像德芙巧克力一样丝滑,不卡顿。方法包括:提前算好 cell 高度(避免滑动时动态计算)、不要在滚动的瞬间做耗时操作(如图片解码)、减少视图层级和特效(如圆角)、把图片解码放到后台等。
7. 什么是组件化?如何实现?
【初级掌握】
组件化是将 App 拆分为多个独立模块,便于复用和维护。实现方式:使用 CocoaPods 私有库、通过路由进行模块间跳转。
【中级扩展】
组件化实现步骤:
- 划分模块:基础组件(网络、存储)、功能组件(分享、支付)、业务组件(首页、我的)。
- 解耦:模块间不直接依赖,通过中间件通信。
-
路由方案:
- URL 路由:通过注册 URL 和对应的模块,利用 openURL 跳转。
- Target-Action 方案:利用 Runtime 解耦,如 CTMediator。
- 私有库管理:使用 CocoaPods 将每个模块打成私有 Pod,通过版本管理。
【高级深入】
组件化的核心是解耦和复用。CTMediator 基于 Target-Action 和 Runtime,通过分类对外提供服务,内部通过 performSelector 调用目标。BeeHive 基于 Spring 思想,使用注解和模块注册,支持模块生命周期管理。还可以采用面向服务架构(SOA),通过接口暴露服务,利用依赖注入容器管理。组件化还需考虑资源共享(如图片、字符串)、持续集成(各模块独立打包)、二进制化(加快编译)等问题。
【通俗解释】
把 App 拆成独立的小部件,每个小部件可以单独开发、测试、复用,就像乐高积木。团队可以分工合作,改一个模块不影响其他模块,而且这些积木还可以用在其他 App 里。
三、初中高工程师回答指南(各层级备考建议)
🔹 初级工程师
- 目标定位:能独立完成简单业务模块,掌握基础 API 使用,理解核心概念。
-
复习重点:
- 语言基础:熟练掌握 OC/Swift 基本语法、内存管理基础(ARC)、常用 Foundation 和 UIKit 类。
- UI 开发:熟悉 Interface Builder、Auto Layout、ViewController 生命周期、常用控件。
- 数据存储:了解 UserDefaults、plist、简单的 SQLite 操作。
- 网络基础:会用 URLSession 发起 GET/POST 请求,解析 JSON。
- 多线程:掌握 GCD 的基本使用(异步、主队列、全局队列)。
- 常见问题:循环引用、代理与通知的区别、KVC/KVO 基本使用。
-
面试技巧:
- 回答问题要简洁,能说出核心概念即可。
- 遇到不会的,可以诚实表示不了解,但尝试从原理上推测。
- 展示学习热情和动手能力(如做过的小项目、GitHub 仓库)。
🔸 中级工程师
- 目标定位:能独立负责复杂模块,理解底层原理,具备性能优化和架构设计能力。
-
复习重点:
- 底层原理:深入理解 Runtime、Runloop、Block、KVO 实现原理。
- 性能优化:启动优化、卡顿监测、内存泄漏排查、包体积优化。
- 架构设计:熟悉 MVC、MVVM 等架构模式,了解组件化思想。
- 多线程进阶:理解 GCD 源码、NSOperation、锁机制、线程安全。
- 网络进阶:HTTPS 握手、证书校验、缓存策略、断点续传。
- 设计模式:掌握常见设计模式并能应用到项目中。
-
面试技巧:
- 回答要有条理,能结合实际项目经验,举例说明。
- 对原理性问题,要能画图或举例说明,比如 Runloop 如何影响界面刷新。
- 主动提出优化方案和踩过的坑,展示解决问题的能力。
🔹 高级工程师
- 目标定位:能主导技术选型、架构重构、团队指导,具备全局视野和深度思考。
-
复习重点:
- 底层深度:Runtime 源码、dyld 加载过程、内存管理细节(Tagged Pointer、散列表)、Mach-O 文件格式。
- 架构演进:组件化、模块化、容器化、跨端方案(React Native、Flutter 对比)。
- 性能极致:监控体系(APM)、自动化工具、崩溃分析(符号化)、启动优化(二进制重排)。
- 工程化:CI/CD 搭建、代码规范、自动化测试、二进制化、Code Review 流程。
- 新技术趋势:SwiftUI、Combine、Concurrency、Swift 6 特性、跨端技术选型。
-
面试技巧:
- 回答要体现深度和广度,能对比不同方案的优劣(如 CTMediator vs BeeHive)。
- 强调解决问题的思路和结果,用数据说话(如启动时间从 2s 降到 0.8s)。
- 展示对团队和流程的改进能力,如何推动技术落地和人才培养。
四、英文术语速查表(中英对照,已核对准确性)
| 中文术语 | 英文术语 |
|---|---|
| 自动引用计数 | Automatic Reference Counting (ARC) |
| 手动引用计数 | Manual Reference Counting (MRC) |
| 运行时 | Runtime |
| 运行循环 | Runloop |
| 多线程 | Multithreading |
| 大中央调度 | Grand Central Dispatch (GCD) |
| 操作队列 | NSOperationQueue |
| 键值编码 | Key-Value Coding (KVC) |
| 键值观察 | Key-Value Observing (KVO) |
| 通知 | Notification |
| 代理 | Delegate |
| 代码块 | Block |
| 视图控制器 | View Controller |
| 自动布局 | Auto Layout |
| 响应链 | Responder Chain |
| 核心动画 | Core Animation |
| 数据持久化 | Data Persistence |
| 结构化查询语言 | SQLite |
| 核心数据 | Core Data |
| 网络会话 | URLSession |
| 超文本传输协议 | HTTP |
| 超文本传输安全协议 | HTTPS |
| 架构模式 | Architecture Pattern |
| 模型-视图-控制器 | Model-View-Controller (MVC) |
| 模型-视图-视图模型 | Model-View-ViewModel (MVVM) |
| 模型-视图-展示器 | Model-View-Presenter (MVP) |
| 设计模式 | Design Pattern |
| 单例 | Singleton |
| 工厂模式 | Factory Pattern |
| 观察者模式 | Observer Pattern |
| 组件化 | Componentization |
| 模块化 | Modularization |
| 持续集成 | Continuous Integration (CI) |
| 持续部署 | Continuous Deployment (CD) |
| 单元测试 | Unit Test |
| UI测试 | UI Test |
| 内存泄漏 | Memory Leak |
| 循环引用 | Retain Cycle / Circular Reference |
| 离屏渲染 | Offscreen Rendering |
| 启动时间 | Launch Time |
| 卡顿 | Stutter / Lag |
| 包体积 | App Size |
| 依赖管理 | Dependency Management |
| CocoaPods | CocoaPods |
| Swift包管理器 | Swift Package Manager (SPM) |
| 版本控制 | Version Control |
| Git | Git |
| 方法调配 | Method Swizzling |
| 关联对象 | Associated Object |
| 自动释放池 | Autorelease Pool |
| 二进制重排 | Binary Reordering |
| 堆栈跟踪 | Stack Trace |
| 符号化 | Symbolication |
以上内容已经过全面修订,确保符合您的要求。如有任何需要调整或补充的地方,请随时告知。