版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Runtime面试题及详细答案(纯实战版)一、基础概念类1.什么是Runtime?它的核心作用是什么?答案:Runtime是Objective-C的一套底层动态运行时库,是OC语言的核心底层支撑,writteninC和汇编。OC中所有的类、对象、方法调用、属性操作,最终都会转化为Runtime的C函数执行。核心作用主要有三点:1.动态类型:编译时不确定方法调用地址,全部延迟到运行时绑定、查找、执行;2.动态操作:运行中可以动态创建类、添加/交换方法、新增属性、遍历成员变量;3.内存与机制支撑:管理对象内存布局、消息转发、协议、分类、KVO等所有OC核心机制。简单来说:OC是静态编译、动态执行,所有动态特性全部依赖Runtime实现。2.谈谈你对OC对象、类、元类的理解,三者的关系是什么?答案:1.实例对象(InstanceObject):我们日常alloc出来的对象,只存储成员变量的值,不存储方法、属性列表,方法全部存在类中。2.类(Class):是一个特殊的对象(类对象),内部存储实例方法列表、属性列表、成员变量列表、协议列表,以及父类指针、元类指针。负责响应实例方法。3.元类(MetaClass):也是一个特殊的类对象,每个类都有唯一元类。元类中存储类方法列表,负责响应类方法。核心链路关系:-实例对象的isa指向类;-类的isa指向元类;-所有元类的isa最终指向NSObject的元类(根元类);-根元类的isa指向自己,形成闭环;-继承链:实例找父类实例,类找父类,元类找父类的元类。3.isa指针的作用是什么?isa指针存储了哪些信息?答案:isa是对象的核心指针,核心作用是告诉对象自己属于哪个类,用于运行时查找方法、判定对象类型。在arm64架构下,isa不再是单纯的指针,是一个联合体(union),复用了多余的存储空间,存储多种信息:1.指针地址:指向所属类/元类的地址;2.extra_rc:对象额外的引用计数;3.has_assoc:是否有关联对象;4.has_cxx_dtor:是否有C++析构函数;5.shiftcls:类的核心地址信息;6.magic:标记是否为初始化完成的对象;7.weakly_referenced:是否被弱引用指向;8.deallocating:对象是否正在释放。二、消息机制核心(面试高频)4.OC方法调用的本质是什么?消息发送的完整流程?答案:OC中[objmethod]方法调用,编译后会被Runtime转化为:objc_msgSend(obj,@selector(method)),本质是发送消息,不是直接调用函数。完整消息发送流程:1.消息发送:通过objc_msgSend开始发送消息,首先通过isa找到对象所属的类;2.缓存查找:优先在类的方法缓存列表(cache)中查找SEL对应的IMP,找到直接执行;3.方法列表查找:缓存未命中,遍历当前类的方法列表,匹配SEL取IMP;4.父类递归查找:当前类没有,顺着superclass指针逐级找父类、根类;5.消息转发:整个继承链都找不到方法,进入消息转发流程,不会直接崩溃;6.崩溃报错:三级转发全部走完仍未处理,抛出unrecognizedselector崩溃。5.详细说下消息转发的三级流程答案:消息查找失败后,会依次触发三级转发,每一级都有机会补救,流程是递进式的:第一级:动态方法解析(补救类方法/实例方法)调用+resolveInstanceMethod:(实例方法未实现)或+resolveClassMethod:(类方法未实现)。可以在这一级动态添加方法实现,返回YES即可拦截报错,重新执行消息查找。第二级:快速消息转发(重定向接收者)调用-forwardingTargetForSelector:。可以指定一个其他对象作为新的消息接收者,将当前未识别的方法转发给其他对象执行,开销极小,属于轻量转发。第三级:完整消息转发(自定义方法签名与调用)先调用-methodSignatureForSelector:获取方法签名,再调用-forwardInvocation:。可以完全自定义方法的执行逻辑、修改参数、转发多个对象、空实现兜底,是最灵活但开销最大的一级。三级全部不处理,最终触发崩溃。6.方法缓存cache的作用和原理?为什么能提升效率?答案:Runtime会对经常调用的方法做缓存,存储SEL和IMP的映射关系。原理:每个类内部有cache哈希表,每次方法调用成功后,会把SEL-IMP缓存下来。下次调用相同方法,无需遍历方法列表和继承链,直接哈希查找匹配IMP。提升效率的核心原因:1.哈希查找时间复杂度O(1),远快于遍历方法列表的O(n);2.避免重复遍历父类继承链,减少多层查找开销;3.日常业务中大部分方法都是高频重复调用,缓存命中率极高。缓存满了会触发扩容、旧缓存清理,保证查询效率。三、方法交换与分类底层7.MethodSwizzling(方法交换)的原理、使用场景、坑点答案:原理:Runtime中每个方法是method结构体,存储SEL、IMP、参数类型等信息。Swizzling本质是交换两个方法的IMP实现地址,调用原SEL时,执行的是新IMP,调用新SEL时执行原IMP。常用场景:1.系统方法兜底拦截(防止数组、字典越界崩溃);2.全局埋点统计(页面点击、按钮点击、页面停留时长);3.统一修改系统控件默认样式、修复系统bug;4.日志统一拦截、参数统一校验。核心坑点(面试重点):1.必须在load方法中执行,且加dispatch_once:避免多次交换导致方法还原、错乱;2.父类子类方法冲突:如果子类未实现该方法,交换父类方法会影响全局父类逻辑;3.三方库重复交换:多个SDK同时hook同一个方法,导致逻辑错乱、递归崩溃;4.未保留原方法实现:新方法内部必须调用原SEL,否则丢失原有系统逻辑。8.load和initialize方法的区别?底层调用时机?答案:对比维度loadinitialize调用时机类/分类被加载进内存时,编译后加载阶段触发类第一次被使用(实例化、调用类方法)时触发,运行时触发调用次数一生只调用一次可能多次,子类未实现会继承父类方法重复调用分类优先级所有分类load都会执行,先父类、再子类、最后分类分类会覆盖主类的initialize,主类不会执行使用场景方法交换、全局hook全局初始化配置、静态变量初始化核心总结:load是加载阶段主动调用,initialize是使用时懒加载调用。9.分类(Category)可以添加属性吗?底层原理是什么?答案:分类不能直接添加成员变量,可以通过Runtime关联对象实现模拟属性。底层原理:1.分类的结构体中,只有方法列表、协议列表、属性列表,没有成员变量列表,所以无法直接存储ivar;2.日常写分类@property,只会生成getter/setter方法声明,不会自动实现方法,也不会生成底层变量存储;3.通过objc_setAssociatedObject和objc_getAssociatedObject,利用Runtime全局哈希表,动态绑定值和对象,实现属性存储。四、KVO底层Runtime原理(必问)10.KVO的底层实现原理?手动触发KVO怎么做?答案:KVO完全基于Runtime动态实现,核心是动态生成子类、重写setter、消息转发。完整底层流程:1.当对一个对象addObserver时,Runtime会动态创建一个原类的子类(命名规则:NSKVONotifying_原类名);2.动态子类内部重写被监听属性的setter方法;3.重写的setter内部会在赋值前后,分别调用willChangeValueForKey、didChangeValueForKey;4.在didChange内部,会触发监听者的observeValueForKeyPath回调;5.同时将原对象的isa指针,指向动态生成的子类,让对象后续调用setter都走子类的实现;6.移除监听后,isa指针还原,动态子类不会销毁,缓存复用。手动触发KVO:手动修改成员变量、绕过setter赋值时,不会自动触发KVO,需要手动调用:[selfwillChangeValueForKey:@"key"];//手动赋值[selfdidChangeValueForKey:@"key"];11.KVO为什么只能监听属性,不能监听成员变量?答案:KVO的核心依赖setter方法的方法拦截。1.属性会自动生成带下划线的成员变量+setter/getter方法,KVO可以重写setter实现监听;2.纯成员变量没有setter方法,直接修改内存地址数值,没有任何方法调用,Runtime无法拦截赋值行为;3.所以只有通过setter赋值的属性,才能被KVO捕获,直接修改ivar无法触发监听。五、内存与实操问题12.objc_msgSend为什么需要参数隐式传self和_cmd?答案:所有OC方法底层都是C函数,两个默认参数是Runtime自动传入的:1.self:当前消息接收者,用于通过isa找类、找方法、访问成员变量;2._cmd:当前方法的SEL选择器,用于在方法内部获取当前方法名、做方法递归拦截、日志统计。没有这两个参数,Runtime无法确定当前是谁在调用、调用的是哪个方法,无法完成动态消息分发。13.什么是野指针?Runtime如何辅助排查野指针问题?答案:野指针:指针指向的内存已经被释放,但指针本身没有置空,依旧指向未知内存地址,访问会触发随机崩溃。Runtime辅助排查方案:1.开启Zombie僵尸对象:对象dealloc后,不会立即释放内存,会标记为僵尸对象,保留类信息;2.当野指针访问已释放对象时,Runtime可以捕获到访问行为,精准打印崩溃类名、调用方法,定位野指针问题;3.日常开发中野指针崩溃无日志、随机性强,依靠原生日志很难定位,Zombie基于Runtime内存标记完美解决。14.动态创建类的使用场景和核心代码逻辑答案:使用场景:动态生成视图模型、动态适配接口字段、热修复简单逻辑、动态埋点类创建。核心流程:1.通过objc_allocateClassPair动态创建类和元类;2.通过class_addIvar添加成员变量;3.通过class_addMethod动态添加方法;4.通过objc_registerClassPair注册类,完成创建;5.使用完毕后可通过objc_disposeClassPair销毁动态类。六、高阶面试压轴题15.为什么OC是动态语言?静态语言和动态语言的区别?答案:OC的动态性全部依托Runtime实现,核心体现在:1.类型动态:id类型编译时不校验真实类型,运行时才确定对象真实类;2.方法动态:编译时不绑定方法地址,运行时动态查找、转发、新增方法;3.结构动态:运行中可以动态改类、加方法、加关联对象,修改类结构。静态、动态语言核心区别:-静态语言(C/C++/Swift静态模式):编译时确定类型、绑定函数地址,运行时无法修改;-动态语言(OC):编译时只做语法校验,核心逻辑全部延迟到运行时处理,灵活度极高。16.消息转发和MethodSwizzling的区别?各自适用场景?答案:区别:1.Swizzling是主动修改方法IMP,从根源替换方法实现,全局生效,提前干预方法执行;2.消息转发是方法找不到后的兜底补救,是报错前的最后拦截,属于被动补救机制,不修改原有方法。适用场景区分:-Swizzling:统一修改系统方法逻辑、全局拦截、修复bug、埋点;-消息转发:做方法兼容、接口适配、多层类方法复用、防止未实现方法崩溃
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 乐园门店商品代销合同范本获取二篇
- 房地产开发商项目销售经理项目完成度KPI考核表
- 餐饮服务员服务态度与效率KPI考核表
- 销售人员业务推广培训通知函(3篇)
- 跨境电商物流时效分析与优化方案
- 人工智能在农产品检测领域的应用与发展指南
- IT技术支持服务解决效率与用户满意度KPI考核表
- 2026年年终财务决算报告提交催办函8篇
- (正式版)DB14∕T 747-2022 《车用甲醇燃料作业规程》
- 金融行业客户服务管理评估表
- 甘肃张掖市肃南裕固族自治县马蹄学校2026-2027学年度第一学期七年级英语课后综合作业(一)(含答案)
- 2026年发展对象培训结业测试及答案解析
- 2026年第一季度家庭医生签约服务培训试卷及答案
- 2026“弘扬长征精神 奋进新征程”知识竞赛题库(含答案解析)
- 导地线展放(张力放线、牵引放线)施工方案
- 银行信访维稳工作方案
- 中信金融资产笔试题
- 四川省水利工程设计概(估)算编制规定2025
- 胃穿孔课件教学课件
- 五级护工考试试题及答案
- 《电动自行车车载北斗卫星定位模块》(征求意见稿编制说明)
评论
0/150
提交评论