iOS高级开发面试题及详细答案(实战向)-1_第1页
iOS高级开发面试题及详细答案(实战向)-1_第2页
iOS高级开发面试题及详细答案(实战向)-1_第3页
iOS高级开发面试题及详细答案(实战向)-1_第4页
iOS高级开发面试题及详细答案(实战向)-1_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

iOS高级开发面试题及详细答案(实战向)本套面试题适配3-5年及以上iOS高级开发岗位,聚焦大厂高频考点、底层原理、线上问题排查、性能优化、项目架构实战,答案摒弃套话,全部为职场实战总结,贴合真实面试口述逻辑。一、Objective-C底层原理(高频核心)1.讲讲OC的消息机制,objc_msgSend执行流程?OC是动态语言,方法调用本质是发送消息,核心函数是objc_msgSend,整体分为三大阶段:第一阶段:消息查找。首先根据receiver的isa指针找到当前类,在类的方法缓存cache中查找方法,如果命中直接调用;缓存未命中,遍历当前类的方法列表(methodList)查找。第二阶段:父类递归查找。当前类未找到,就沿着继承链一层层找父类的方法列表,直到NSObject。如果顶层父类依然未找到,进入消息转发流程。第三阶段:消息转发。分为三次补救,第一次调用resolveInstanceMethod,动态添加方法实现;第二次调用forwardingTargetForSelector,将消息转发给其他对象处理;第三次开启完整转发,通过methodSignatureForSelector生成方法签名,再由forwardInvocation自定义消息处理逻辑。三次补救全部失败,才会报经典的unrecognizedselector崩溃。补充:日常开发中大部分找不到方法的崩溃,都是没有走任何消息转发补救导致的。2.什么是isa指针?isa走位流程是什么?isa是每个OC对象、类对象都持有的指针,核心作用是绑定对象和它的类,用来查找方法和属性。真机环境下isa是优化后的isa_t结构体,不是单纯的指针,复用了多余的比特位存储类信息、引用计数、是否弱引用、是否正在释放等标记,节省内存空间。完整isa走位:实例对象isa->类isa->元类isa->根元类isa->根元类(自闭环)。简单理解:实例对象存成员变量,类对象存实例方法,元类存类方法,所有元类最终归属于根元类,形成闭环,保证类方法调用的底层逻辑统一。3.分类(Category)能不能加成员变量?为什么?如何实现?分类不能直接添加成员变量。原因:类的成员变量列表ivarList在编译时就确定了,分类是运行时动态加载的结构体,底层结构只有方法列表、协议列表、属性列表,没有成员变量列表,无法修改原有类的内存布局,所以直接写成员变量会编译报错。解决方案:通过Runtime的关联对象实现伪成员变量。使用objc_setAssociatedObject、objc_getAssociatedObject绑定值和对象。注意点:关联对象不是存在对象本身内存中,是存在全局的关联表中;同时要注意内存管理策略,assign修饰对象会出现野指针问题,对象销毁时不会自动清空关联值,大概率造成内存泄漏。4.Runtime常用场景,项目中实际用过哪些?都是实战高频场景,我项目中主要用到这几个:1.字典转模型:利用Runtime遍历类的所有成员变量,自动映射字典key和模型属性,替代手动赋值,简化代码。2.方法交换(Hook):拦截系统方法,统一做全局逻辑。比如拦截UIButton的点击方法,统一处理按钮防重复点击、统计页面点击埋点;拦截View的生命周期方法做页面监控。3.关联对象:分类扩展属性、给系统控件添加自定义标记、存储临时数据。4.消息转发容错:针对部分兼容老版本接口的方法,做消息转发兜底,避免线上未实现方法导致的崩溃。二、内存管理&循环引用(高级必考)1.OC内存管理机制原理,MRC和ARC区别?OC采用引用计数内存管理,核心规则:谁创建、谁持有、谁释放。MRC是手动管理,需要开发者手动写retain、release、autorelease,完全靠开发者控制引用计数,自由度高但极易出错,野指针、内存泄漏频发。ARC是编译器自动管理,编译阶段编译器会自动在合适位置插入retain、release、autorelease代码,运行时逻辑和MRC完全一致,只是省去手动编码。ARC不是彻底杜绝内存问题,循环引用、野指针问题依然存在。2.常见的循环引用场景及解决方案?高频循环引用场景:1.Block内部引用外部self,同时self持有block;2.代理delegate强引用;3.两个对象互相强引用对方;4.闭包嵌套多层引用外部对象。解决方案:1.Block场景:使用__weak修饰self,打破持有环;耗时异步操作中如果怕self提前释放,可在内部用__strong临时持有,保证任务完成。2.代理统一用weak修饰,绝对不用strong;3.双向引用场景,一方用strong、一方用weak,单向持有即可。3.__weak、__strong、__unsafe_unretained区别?__strong:默认修饰符,强引用,持有对象,引用计数+1,对象不会被释放,正常变量默认都是这个。__weak:弱引用,不增加引用计数,不持有对象。当对象销毁时,弱引用指针会自动置空,不会产生野指针,专门用来解决循环引用。__unsafe_unretained:无安全引用,不增计数、不置空。对象销毁后,指针依然指向原内存地址,会产生野指针,直接崩溃,现在项目基本不用,仅兼容老代码。4.AutoreleasePool原理及作用?自动释放池是一个栈结构,用来管理autorelease对象。调用autorelease的对象,不会立刻释放,会被加入当前释放池,等待池子销毁时统一批量release。主线程默认会创建自动释放池,RunLoop每次循环迭代结束,会自动清空池子,释放临时对象。实战场景:批量创建大量临时对象(比如列表大量cell数据解析、图片处理),会造成瞬时内存峰值,需要手动创建@autoreleasepool包裹,及时释放临时对象,降低内存占用。三、多线程&GCD底层与实战1.GCD队列和任务的区别,串行、并行队列区别?任务就是要执行的代码块(block),队列是用来存放任务的容器,遵循先进先出原则。串行队列:同一时间只执行一个任务,任务按顺序逐个执行,必须等上一个任务结束,才会执行下一个。并行队列:可以同时开启多个线程,并发执行多个任务,任务执行顺序不确定,取决于系统线程调度。核心注意:并行队列不一定并发,只有异步执行才会开启多线程;同步执行无论串行还是并行,都在当前线程执行,不会开辟新线程。2.sync、async区别?死锁场景及原理?sync同步:阻塞当前线程,等待任务执行完成,才会继续往下走,不开启新线程。async异步:不阻塞当前线程,直接往下执行,系统自动开辟线程执行任务。最常见死锁:主线程中调用dispatch_sync执行主队列任务。原理:主线程正在执行当前代码,sync要求等待队列任务完成,而主队列任务需要等待主线程空闲才能执行,互相等待,形成死锁。补充:串行队列嵌套sync执行当前队列任务,同样会死锁,原理一致。3.GCD信号量、栅栏函数的实战用法?栅栏函数dispatch_barrier:用于并行队列中,隔离读写操作。栅栏任务执行前,所有之前的任务全部完成;栅栏任务执行期间,所有新任务等待;栅栏执行完,后续任务继续并发执行。项目中用来解决异步并发读写数据冲突问题。信号量dispatch_semaphore:核心是控制最大并发数、做线程同步、异步任务转同步。实战场景:限制网络请求最大并发数、等待多个异步任务全部完成后统一回调、解决多线程数据抢夺问题。4.RunLoop原理及实战使用场景?RunLoop是运行循环,本质是一个死循环,用来保活线程、监听事件、处理任务,让线程有事做事、没事休眠,不消耗CPU。主线程RunLoop默认开启,保证APP不退出;子线程默认没有RunLoop,执行完任务就销毁。核心模式:默认模式、追踪滚动模式、公共模式。不同模式下监听的事件源不同。实战场景:1.保活子线程:常驻子线程处理定时任务、后台任务;2.解决NSTimer滚动卡顿问题:将timer加入公共模式;3.监听页面刷新、触摸事件、网络回调事件;4.处理延迟执行、任务调度。四、Swift进阶核心(高级必问)1.Swift中struct和class本质区别?1.存储方式:struct是值类型,存在栈内存;class是引用类型,栈存指针、堆存对象。2.赋值逻辑:结构体赋值是完整拷贝,新旧对象互不影响;类赋值是指针拷贝,多个变量指向同一个对象,修改互相影响。3.继承性:结构体不支持继承,类支持继承、重写。4.内存管理:结构体无需内存管理,自动销毁;类依靠ARC引用计数管理内存,存在循环引用风险。5.多态:结构体无多态,类支持多态。2.Swift闭包的内存管理,循环引用如何解决?Swift闭包默认会强引用内部捕获的变量,如果self持有闭包,闭包又持有self,直接形成循环引用。解决方案:1.捕获列表:[weakself]、[unownedself]打破循环;2.区分使用场景:weak适合对象可能提前销毁的场景,可选解包,安全无崩溃;unowned适合生命周期一致、不会提前销毁的场景,类似OC__unsafe_unretained,速度更快,使用不当会崩溃。3.lazy懒加载原理和使用注意事项?lazy修饰的属性,第一次访问时才初始化,延迟加载,节省启动内存,避免无用对象初始化。注意点:1.懒加载属性必须是变量var,不能是常量let;2.懒加载线程不安全,多线程同时访问可能重复创建对象,多线程场景需要加锁;3.懒加载闭包中可以直接使用self,不会循环引用。4.Optional可选类型原理,隐式解包和强制解包区别?Optional是枚举类型,包含none和some两种状态,本质是对值的包装,可以为空,解决OC空指针无报错的问题。强制解包(!):直接强行取值,如果为nil直接崩溃,只用于百分百确定非空的场景。隐式解包(!定义变量):变量默认自动解包,不用每次写?/!,适合初始化后永远不为空的属性,比如控制器的view、控件属性。日常开发优先使用可选绑定、空合运算符,尽量避免强制解包。五、UI渲染&性能优化(实战高频)1.UI渲染原理,CPU、GPU分工?CPU负责:代码逻辑计算、布局计算、文本绘制、图片解码、图层树构建,属于逻辑处理。GPU负责:图层合成、纹理渲染、像素填充、画面输出到屏幕,专注图形渲染。卡顿核心原因:CPU耗时过长导致来不及提交渲染任务,或者GPU过度渲染、图层过多、离屏渲染过多,导致帧率下降。2.什么是离屏渲染?哪些场景会触发?如何优化?正常渲染是在当前屏幕缓冲区渲染,离屏渲染是GPU需要开辟新的缓冲区,先在离线缓冲区渲染,再合成到屏幕,多了一次缓冲区切换,非常消耗性能,是列表卡顿的主要原因之一。触发场景:1.圆角+裁剪同时开启;2.阴影、遮罩、图层混合;3.光栅化不当使用。优化方案:1.图片圆角优先用裁剪后的静态图片替代代码圆角;2.阴影单独设置路径,减少渲染计算;3.合理开启shouldRasterize光栅化,缓存静态图层,禁止动态变化图层光栅化;4.减少图层嵌套,尽量扁平化UI。3.列表卡顿优化完整方案?我日常项目中落地的全套优化方案:1.预处理数据:提前计算cell高度、缓存高度,避免滑动时实时计算;2.减少离屏渲染:规避圆角阴影叠加问题,扁平化图层;3.异步渲染:文本、图片绘制放到子线程,主线程只做赋值和布局;4.图片优化:图片预解码、适配尺寸、避免大图缩放渲染;5.滑动优化:列表滑动时停止刷新、停止网络请求,滑动结束再更新UI;6.复用机制优化:保证cell彻底复用,避免重复创建控件;7.减少主线程耗时:数据解析、模型转换、文件操作全部放子线程。4.启动优化怎么做?如何衡量启动耗时?启动分为冷启动、热启动,优化核心是减少主线程耗时、减少初始化任务。优化方案:1.梳理main函数之前耗时:精简无用动态库、删除冗余编译代码、优化链接耗时;2.main函数之后:把非必要的初始化任务(统计、第三方SDK、缓存清理)异步延迟加载,不阻塞主线程;3.懒加载所有非刚需资源,避免启动一次性加载大量图片、配置文件;4.去除冗余代码、无用分类、重复初始化逻辑。衡量方式:通过Xcode启动耗时工具、自定义启动打点(main开始到首帧渲染完成)、线上埋点统计用户真实启动耗时。六、编译链接&底层进阶1.iOS编译链接过程?静态库、动态库区别?编译流程:预处理->编译->汇编->链接。预处理:替换宏、导入头文件、删除注释;编译:语法语义检查,生成汇编代码;汇编:转成机器码目标文件;链接:合并所有目标文件、库文件,生成可执行文件。静态库.a:编译时直接打包进项目,体积大,更新需要重新打包编译,运行速度快,无依赖问题。动态库.dylib:编译时不打包,运行时动态加载,体积小、可单独更新,系统框架都是动态库,过多自定义动态库会增加启动耗时。2.野指针和内存泄漏的区别,如何排查?野指针:指针指向已经销毁的内存,访问野指针会直接闪退、崩溃,属于即时问题。内存泄漏:对象持有关系未断开,对象无法释放,内存一直占用不回收,不会立刻崩溃,只会导致内存持续升高、页面卡顿、后台被杀。排查工具:XcodeInstruments(Zombies查野指针、Leaks查内存泄漏)、MLeaksFinder第三方检测、线上崩溃日志分析、内存快照对比。七、项目架构&实战问题(高阶面试)1.MVC、MVVM区别,项目中为什么用MVVM?MVC:Controller承载大量逻辑,业务逻辑、数据处理、视图逻辑全部堆在控制器中,极易臃肿,代码耦合度高,难维护、难测试。MVVM:拆分出ViewModel,专门处理业务逻辑、数据转换、网络请求,View和ViewModel双向绑定,Controller只负责页面初始化和视图调度。优势:代码解耦、职责清晰、控制器轻量化、逻辑可复用、方便单元测试,适合中大型项目迭代维护。2.组件化架构的实现思路,解决什么问题?中大型项目代码臃肿、模块耦合严重、编译速度慢、多人开发冲突多,所以需要组件化。核心思路:将项目按业务拆分为独立组件,每个组件独立开发、独立编译、独立运行,组件之间不直接依赖,通

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论