2020-12-16 10:39:05
以下整理了2020年春招中常见的iOS开发面试题,涵盖runtime、内存管理、多线程、架构设计等核心知识点,帮助高效刷题备战面试。
内存模型
isa:指向类或元类的指针,普通对象指向类,类对象指向元类。
对象结构:包含isa、成员变量等。
类结构:包含superclass、方法缓存、方法列表等。
metaclass:存储类的类方法,所有元类的isa指向根元类(NSObject的元类),形成闭环。
结构体存储:class_rw_t(可读写,含方法列表、属性、协议)、class_ro_t(只读,编译期确定)。
metaclass设计原因统一管理类方法,使类对象能调用类方法(如+ (void)method),避免与实例方法混淆。
class_copyIvarList vs class_copyPropertyList
IvarList:返回所有成员变量(包括@private和@protected)。
PropertyList:仅返回@property声明的属性(自动合成实例变量)。
class_rw_t与class_ro_t区别
ro_t:编译期确定,存储方法、属性、协议的初始列表。
rw_t:运行时动态添加方法或属性时使用,包含ro_t和可修改的列表。
Category加载机制
加载顺序:按编译顺序加载,后编译的Category方法覆盖先编译的。
同名方法:后加载的Category方法会覆盖先加载的。
load方法:在main函数执行前调用,按编译顺序执行。
Category vs Extension
Extension:需在.m文件中声明,可添加实例变量和私有方法。
Category:无法添加实例变量,只能扩展方法。
NSObject Extension:可添加,但需在.m文件中实现。
消息转发机制
步骤:动态方法解析 → 备用接收者 → 完整消息转发。
优势:灵活(如实现多继承),但性能较低(需多次查找)。
与其他语言对比:Java/C#通过接口或虚函数表实现,更高效但灵活性差。
方法调用流程
缓存查找:优先在方法缓存中查找IMP。
动态解析:若未找到,调用+resolveInstanceMethod:动态添加方法。
消息转发:若仍未解决,进入转发流程。
IMP、SEL、Method区别
SEL:方法选择器,类型为char*的唯一标识。
IMP:函数指针,指向方法实现(id (*)(id, SEL, ...))。
Method:结构体,包含SEL和IMP。
load vs initialize方法
load:在main函数前调用,每个类/Category仅一次,按编译顺序执行。
initialize:在首次发送消息前调用,子类未实现时会调用父类方法,仅一次。
weak实现原理
SideTable:全局哈希表,键为对象地址,值为SideTableEntry(包含引用计数和弱引用表)。
弱引用表:存储指向对象的weak指针,对象释放时将所有weak指针置为nil。
关联对象实现
存储:通过ObjectAssociationsMap全局哈希表管理,键为对象地址,值为关联对象列表。
内存管理:关联对象遵循普通对象的引用计数规则,需手动管理或使用OBJC_ASSOCIATION_RETAIN等策略。
Autoreleasepool原理
数据结构:栈结构的AutoreleasePoolPage(每个页4096字节),包含next指针和thread字段。
操作:push时压入POOL_BOUNDARY,pop时释放next之前的对象。
ARC实现原理
编译期优化:插入retain/release代码,消除冗余操作(如局部变量无需release)。
优化技术:合并相邻的retain/release,使用objc_storeStrong替代直接操作。
ARC内存泄漏场景
循环引用:如Delegate属性用strong修饰。
未释放资源:如NSTimer未调用invalidate。
C语言资源:如malloc分配的内存未free。
GCD队列类型
串行队列:任务按顺序执行。
并发队列:任务并发执行(系统提供全局并发队列)。
主队列:串行队列,与主线程关联。
自定义队列:通过dispatch_queue_create创建。
GCD方法API
同步任务:dispatch_sync(阻塞当前线程)。
异步任务:dispatch_async(非阻塞)。
单次执行:dispatch_once(保证代码仅执行一次)。
死锁场景
主队列同步任务:如dispatch_sync(dispatch_get_main_queue(), ^{})会导致死锁。
串行队列嵌套:在串行队列中同步派发任务到同一队列。
线程锁类型
@synchronized:递归锁,性能较低。
NSLock:普通互斥锁。
NSRecursiveLock:递归锁,允许同一线程多次加锁。
pthread_mutex:C语言级锁,性能更高。
AutoLayout原理
约束引擎:通过线性方程计算帧,使用Cassowary算法解决冲突。
性能优化:减少约束数量,避免复杂视图层级。
UIView vs CALayer
UIView:负责事件处理、视图层级管理。
CALayer:负责渲染、动画,包含contents(显示内容)和sublayers。
离屏渲染
触发条件:圆角、阴影、遮罩等需额外绘制的操作。
优化:提前合成图片(如用UIBezierPath绘制圆角)。
imageName vs imageWithContentsOfFile
imageName:缓存到系统,适合重复使用的图片。
imageWithContentsOfFile:不缓存,适合大图或一次性图片。
启动优化
监控工具:Instruments的Time Profiler。
优化方法:延迟初始化非关键资源、减少dylib加载数量。
卡顿优化
监控:CADisplayLink检测帧率,Instruments的Core Animation工具。
优化:减少主线程耗时操作(如JSON解析)、优化drawRect。
耗电优化
监控:Energy Log。
优化:减少定位、网络请求频率,使用WKWebView替代UIWebView。
设计模式
MVC:Model-View-Controller,适合简单项目。
MVVM:Model-View-ViewModel,通过RAC或KVO绑定数据。
VIPER:View-Interactor-Presenter-Entity-Router,适合大型项目。
路由方案
`