核心说明聚焦面试高频提问全程直击考点无冗余表述覆盖Runtime底层本质、核心数据结构、核心机制消息传递、动态解析等、实操应用及面试延伸点兼顾理论深度与实操应答性可直接用于面试背诵。一、Runtime 核心定义面试开篇必答面试必记Runtime运行时是 Objective-C 的动态运行时系统本质是一套用C语言编写的底层API函数库核心作用是让OC语言在运行期而非编译期完成消息分发、方法解析、动态扩展等操作是OC语言“动态性”的核心支撑。OC的方法调用本质上不是直接调用函数而是通过Runtime发送消息实现的。补充考点Runtime分为两种—— Legacy Runtime早期iOS设备/32位设备和 Modern Runtime当前主流64位设备面试重点考察Modern Runtime核心差异是类结构的存储方式不同。二、Runtime 核心数据结构必背面试高频Runtime的所有机制都基于底层核心结构体实现无需背诵完整源码重点掌握结构组成、核心作用及关联关系以下是面试必考的4个核心结构体2.1 objc_object对象结构体所有OC对象的底层本质OC中所有对象实例对象、类对象、元类的底层都是objc_object结构体核心只有一个成员——isa指针这是对象能关联到类、实现动态特性的核心。// 简化源码面试重点记忆 struct objc_object { isa_t isa; // 核心指向类对象/元类决定对象的类型 };isa指针面试重中之重现代Runtime中采用非指针isanon-pointer isa利用64位系统的空闲位存储引用计数、是否被弱引用等额外信息减少内存访问层级提升性能延伸id类型的本质是typedef struct objc_object *id即指向objc_object结构体的指针因此id可以指向任何OC对象。2.2 objc_class类结构体类对象/元类的底层本质类对象、元类的底层都是objc_class结构体且objc_class继承自objc_object因此类本身也是一个对象核心存储类的相关信息决定类的方法、属性、协议等。// 简化源码面试重点记忆核心成员 struct objc_class : objc_object { isa_t isa; // 指向元类类对象的isa Class superclass; // 指向父类形成继承链 cache_t cache; // 方法缓存优化方法查找效率 class_data_bits_t bits; // 存储类的方法、属性、协议列表核心 };isa指针类对象的isa指向元类存储类方法元类的isa指向根元类根元类的isa指向自身superclass指针类对象的superclass指向父类对象元类的superclass指向父类的元类根元类的superclass指向根类对象如NSObject形成继承链cache缓存存储最近调用过的方法SELIMP下次调用时直接从缓存中查找避免重复遍历方法列表提升性能bits字段通过bits可访问class_rw_t和class_ro_t结构体是类信息的核心存储载体。2.3 class_ro_t 与 class_rw_t类信息存储结构体二者不直接属于objc_class而是通过bits字段间接访问核心区别是“只读/可读写”面试常考二者差异class_ro_t只读结构体编译期确定存储类的只读信息无法修改如类名、编译期确定的方法列表baseMethodList、成员变量ivars、属性baseProperties等class_rw_t可读写结构体类首次使用前realize阶段创建存储可动态扩展的信息如Category添加的方法、属性、协议以及类的子类列表等面试延伸Category的方法能“覆盖”原类方法本质是Category的方法被添加到class_rw_t的方法列表中且优先级高于原类方法后编译的Category方法优先级更高。2.4 Method / SEL / IMP方法相关核心结构体面试必背三者是Runtime方法调用的核心需明确各自含义、关联关系面试常考“三者关系”SEL选择器本质typedef struct objc_selector *SEL是方法名在Runtime中的唯一标识相同方法名对应同一个SEL无论所属哪个类获取方式selector(methodName)或sel_registerName(methodName)核心作用用于查找方法的实现IMP。IMP方法实现指针本质typedef id (*IMP)(id, SEL, ...)是指向方法具体实现代码的函数指针核心作用拿到IMP后可直接调用方法跳过Runtime消息查找流程是Method Swizzling的核心。Method方法结构体本质typedef struct objc_method *Method是SEL和IMP的配对关系还包含方法的类型编码method_types核心作用关联方法名SEL和方法实现IMPRuntime通过SEL查找对应的Method再通过Method获取IMP。三者关系面试必答SEL是方法的“名字”IMP是方法的“实现地址”Method是将“名字”和“地址”绑定起来的“桥梁”。2.5 补充元类Meta-Class面试难点元类是类对象的“类”核心作用是存储类方法面试需牢记以下逻辑必背实例对象的isa → 类对象存储实例方法类对象的isa → 元类存储类方法元类的isa → 根元类NSObject的元类根元类的isa → 自身核心结论实例方法存在类对象中类方法存在元类中元类也遵循继承链与类的继承链一致。三、Runtime 核心机制面试重中之重必考Runtime的核心机制围绕“动态性”展开重点掌握4个核心机制每个机制需牢记“原理流程面试考点”其中消息传递和消息转发是高频难点。3.1 核心机制1消息传递objc_msgSendOC方法调用的本质面试必记OC中所有方法调用如[obj method]编译后都会被转换为Runtime的objc_msgSend函数调用本质是“发送消息”而非直接调用函数流程如下必背通过实例对象obj的isa指针找到其对应的类对象在类对象的cache方法缓存中查找对应的SEL找到则获取IMP调用方法实现流程结束若cache中未找到遍历类对象的methodList方法列表找到对应的Method获取IMP并调用同时将该方法加入cache缓存优化若类对象中未找到通过superclass指针找到父类对象重复步骤2-3直到根类NSObject若根类中仍未找到进入“消息转发”流程若未实现转发报错unrecognized selector sent to instance。面试延伸1objc_msgSend的参数的核心是“接收者obj”和“选择器SEL”还可传递额外参数底层会自动处理参数和返回值面试延伸2cache的缓存策略——LRU最近最少使用当缓存满时会移除最久未使用的方法保证缓存的都是常用方法。3.2 核心机制2消息转发解决“方法未找到”的核心面试难点当消息传递流程中从自身到根类都未找到对应SEL时Runtime会触发消息转发机制给开发者一次“补救机会”避免程序崩溃转发流程分3步必背按优先级排序第一步动态方法解析最优先尝试自己添加方法实现实例方法未找到调用类的 (BOOL)resolveInstanceMethod:(SEL)sel类方法未找到调用类的 (BOOL)resolveClassMethod:(SEL)sel核心逻辑在该方法中通过class_addMethod动态添加SEL对应的IMP返回YES表示解析成功消息传递流程继续返回NO进入下一步转发。代码示例实例方法解析// 动态解析未实现的实例方法 (BOOL)resolveInstanceMethod:(SEL)sel { if (sel selector(unimplementedMethod)) { // 动态添加方法实现参数类、SEL、IMP、类型编码 class_addMethod(self, sel, (IMP)dynamicMethodImpl, v:); return YES; } return [super resolveInstanceMethod:sel]; } // 方法实现 void dynamicMethodImpl(id self, SEL _cmd) { NSLog(动态解析方法执行); }第二步快速转发尝试将消息转发给其他对象调用方法- (id)forwardingTargetForSelector:(SEL)aSelector实例方法核心逻辑返回一个能处理该SEL的对象非nilRuntime会将消息转发给该对象由该对象执行消息传递流程返回nil进入下一步转发面试延伸快速转发仅能转发给“一个对象”无法修改消息的SEL和参数。第三步慢速转发完整转发可修改消息内容核心逻辑将消息包装成NSInvocation对象开发者可修改消息的接收者、SEL、参数再转发给其他对象流程如下调用- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector返回该SEL的方法签名描述参数和返回值类型若返回nil程序崩溃若返回有效方法签名调用- (void)forwardInvocation:(NSInvocation *)anInvocation在forwardInvocation中通过[anInvocation invokeWithTarget:target]将消息转发给目标对象还可修改anInvocation的参数、SEL等。面试延伸慢速转发比快速转发更灵活但性能略低因为需要包装NSInvocation对象。3.3 核心机制3动态方法决议Method Swizzling黑魔法面试高频Method Swizzling方法交换是Runtime最常用的实操场景本质是“交换两个Method的IMP”实现“偷换方法实现”常用于AOP面向切面编程、Hook方法、统一埋点、崩溃防护等。核心原理通过Runtime API获取两个Method的IMP然后交换二者的IMP使得调用原方法时实际执行的是交换后的方法实现核心API必背- class_getInstanceMethod(Class cls, SEL sel)获取实例方法 - class_getClassMethod(Class cls, SEL sel)获取类方法 - method_exchangeImplementations(Method m1, Method m2)交换两个方法的IMP。代码示例Hook UIViewController的viewDidLoad方法implementation UIViewController (Swizzling) (void)load { // 确保只执行一次避免Category多次加载重复交换 static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ // 获取原方法和自定义方法 Method originalMethod class_getInstanceMethod(self, selector(viewDidLoad)); Method swizzledMethod class_getInstanceMethod(self, selector(swizzled_viewDidLoad)); // 交换方法实现 method_exchangeImplementations(originalMethod, swizzledMethod); }); } // 自定义方法替换后的实现 - (void)swizzled_viewDidLoad { // 执行原viewDidLoad逻辑此时调用swizzled_viewDidLoad实际执行原实现 [self swizzled_viewDidLoad]; // 新增自定义逻辑如埋点、打印日志 NSLog(viewDidLoad 被调用了); } end面试注意事项必背避免踩坑在load方法中执行交换且用dispatch_once保证只交换一次load方法会在类加载时自动调用且每个类只调用一次避免交换系统方法后未调用原方法实现导致系统逻辑异常若原方法可能不存在需先通过class_addMethod添加方法再进行交换命名规范自定义方法名加前缀避免与其他Category方法重名。3.4 核心机制4动态属性与关联对象Associated ObjectsOC中Category不能直接添加成员变量但可通过Runtime的关联对象机制给分类动态添加“伪属性”本质是将属性值与对象关联存储面试常考使用场景和API。核心API必背- objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)给对象添加关联对象 - objc_getAssociatedObject(id object, const void *key)获取对象的关联对象 - objc_removeAssociatedObjects(id object)移除对象的所有关联对象不推荐建议按需移除。关联策略objc_AssociationPolicy面试必记OBJC_ASSOCIATION_ASSIGN弱引用不增加引用计数类似assign可能产生野指针OBJC_ASSOCIATION_RETAIN_NONATOMIC强引用非原子性类似strong、nonatomicOBJC_ASSOCIATION_COPY_NONATOMIC复制非原子性类似copy、nonatomicOBJC_ASSOCIATION_RETAIN强引用原子性OBJC_ASSOCIATION_COPY复制原子性较少用。代码示例给Category添加动态属性interface NSObject (AssociatedProperty) // 动态添加的伪属性 property (nonatomic, strong) NSString *customName; end implementation NSObject (AssociatedProperty) // 关联对象的key需唯一常用static const void * static const void *CustomNameKey CustomNameKey; - (void)setCustomName:(NSString *)customName { // 添加关联对象强引用、非原子性 objc_setAssociatedObject(self, CustomNameKey, customName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSString *)customName { // 获取关联对象 return objc_getAssociatedObject(self, CustomNameKey); } end面试延伸关联对象的存储位置——不存储在对象本身objc_object而是存储在Runtime的全局哈希表中通过对象指针和key关联查找因此不会影响对象的内存布局。四、Runtime 其他面试高频考点延伸必记1. Runtime的动态性体现面试必答动态消息传递运行时才确定调用哪个方法而非编译期动态方法解析运行时动态添加方法实现动态交换方法运行时交换两个方法的实现动态添加属性通过关联对象给对象动态添加属性动态创建类通过objc_allocateClassPair动态创建类objc_registerClassPair注册类。2. 分类Category的底层实现结合RuntimeCategory的底层是objc_category结构体存储类名、协议、方法、属性等信息编译时Category不会修改原类的结构而是在运行时通过Runtime将Category的方法、属性、协议合并到原类的class_rw_t中若Category与原类有同名方法Category的方法会覆盖原类方法本质是Category的方法被添加到方法列表前面查找时先找到多个Category同名方法编译顺序决定优先级后编译的Category方法覆盖先编译的。3. weak指针的底层实现结合Runtimeweak指针的底层依赖Runtime的SideTable结构包含weak_table哈希表当对象被销毁引用计数为0时Runtime会遍历weak_table中该对象的所有weak指针将其自动置为nil避免野指针weak指针不会增加对象的引用计数这是与strong指针的核心区别。4. Runtime的应用场景面试必答结合实操崩溃防护Hook系统方法如NSArray的objectAtIndex:避免数组越界、字典nil值等崩溃统一埋点通过Method Swizzling Hook页面跳转、按钮点击等方法统一添加埋点逻辑组件化通信通过关联对象、动态方法调用实现组件间解耦通信JSON模型转换通过Runtime遍历对象的属性自动将JSON字典转换为模型对象如MJExtension底层原理自定义KVO基于Runtime的消息转发、方法交换实现KVO的底层逻辑。五、面试高频问答直接应答无需修改问题1Runtime是什么OC的动态性靠什么实现应答Runtime是OC的动态运行时系统本质是一套C语言API核心作用是让OC在运行期完成消息传递、方法解析、动态扩展等操作OC的动态性完全靠Runtime实现编译期仅确定消息的发送运行期才确定方法的实现。问题2OC方法调用的本质是什么消息传递的流程是什么应答本质是Runtime发送消息编译后转换为objc_msgSend函数调用流程1. 通过对象isa找到类对象2. 查找类对象的cache和方法列表找到则调用IMP3. 未找到则遍历父类继承链4. 仍未找到则进入消息转发流程未实现转发则崩溃。问题3消息转发的流程是什么分几步应答分3步按优先级排序1. 动态方法解析resolveInstanceMethod:尝试动态添加方法实现2. 快速转发forwardingTargetForSelector:转发给其他对象3. 慢速转发methodSignatureForSelector: forwardInvocation:包装成NSInvocation转发可修改消息内容。问题4Method Swizzling的原理是什么使用时需要注意什么应答原理是通过Runtime API交换两个Method的IMP实现方法实现的偷换注意事项1. 在load方法中执行用dispatch_once保证只交换一次2. 交换后需调用原方法实现避免系统逻辑异常3. 避免方法名重名自定义方法加前缀4. 原方法不存在时需先添加方法再交换。问题5Category为什么不能直接添加成员变量如何给Category添加属性应答因为Category的底层结构中没有存储成员变量的字段编译时不会修改原类的内存布局因此不能直接添加成员变量可通过Runtime的关联对象机制给Category添加“伪属性”本质是将属性值与对象关联存储在全局哈希表中。问题6SEL、IMP、Method三者的关系是什么应答SEL是方法的唯一标识名字IMP是方法的具体实现指针地址Method是将SEL和IMP绑定起来的桥梁Runtime通过SEL找到对应的Method再通过Method获取IMP从而调用方法。问题7元类是什么作用是什么应答元类是类对象的“类”底层也是objc_class结构体核心作用是存储类方法类对象的isa指向元类因此调用类方法时Runtime会去元类中查找方法实现。六、面试总结核心提炼快速背诵1. 底层核心Runtime是C语言API是OC动态性的核心所有OC方法调用本质是消息传递objc_msgSend2. 数据结构重点记objc_objectisa、objc_classisa、superclass、cache、bits、SEL/IMP/Method以及元类的作用3. 核心机制消息传递流程必背、消息转发3步流程必背、Method Swizzling原理注意事项示例、关联对象API策略4. 延伸考点Category底层实现、weak指针底层、动态性体现、应用场景5. 面试关键能说出核心机制的流程、原理结合代码示例应答重点掌握消息转发和Method Swizzling面试必考。