ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

网易iOS校招笔试题深度解析:runtime、内存管理与RunLoop考点全拆解

网易iOS校招笔试题深度解析:runtime、内存管理与RunLoop考点全拆解 那年九月的深夜我在线做完网易2018校招iOS开发工程师笔试卷时最大的感受不是题目难而是“这套题出得真老辣”。它不考你Swift最新语法背得有多熟也不问某个API的拼写而是把iOS开发最核心的底层逻辑、计算机基础和你平时写代码时会不会追问“为什么”的习惯一次性摊开来放在你面前。距离那场考试过去这么多年回看这套题它依然是校招iOS岗笔试题里很有参考价值的一套尤其是如果你想进的是那种重视技术深度的大厂。这篇内容不打算复述具体题目毕竟网上已经能搜到原卷而是把整套卷子按考点拆开讲讲每类题到底在考察什么、背后对应的知识盲区是什么、以及我后来在自己带实习生的过程中发现哪些坑是应届生最容易踩的。无论你是正在准备校招还是打算跳槽想检验一下自己的基础这篇都值得你花二十分钟读完。1. 拆卷第一印象这套题在考什么又故意不考什么1.1 卷面结构和考核落点网易2018校招iOS笔试卷整体分两大块客观题选择题为主和主观编程题。客观题覆盖语言基础、内存管理、UIKit、计算机网络、操作系统和少量数据结构主观题则是标准的算法/编程实现。整体难度不是“题题致命”而是呈阶梯状前面有送分题中段有需要细想才能避开陷阱的题压轴则用来区分谁真正写过代码、谁只是背了八股。这套题最值得玩味的是它的“取舍”。2018年Swift已经出了4.0iOS 11也普及了但卷面上大量题目依然围绕Objective-C展开尤其是runtime、消息转发、内存管理这些OC的底层机制。这不是网易保守而是成熟App的业务代码里OC存量太大面试官想找的是一个能上手存量工程、能排查疑难Crash的人而不是只会在Playground里写Swift脚本的人。1.2 它的筛选逻辑基础扎实比什么都重要另一个让我印象深刻的点是这套题非常克制地避开了“偏难怪”的纯记忆类问题比如某个iOS 11新增API的名字、某个代理方法的精确拼写。它考的全是“你只要认真写过几个月代码就一定能答上来但如果只是刷题背书一定会卡壳”的内容block为什么会导致循环引用、viewDidLoad和viewWillAppear到底谁先谁后、copy修饰符用错会发生什么。这种出题思路对应的是校园招聘的核心筛选逻辑应届生没有太多项目经验可以聊面试官只能通过你对基础知识的掌握程度来判断你未来能不能在真实工程里生存下来。基本功扎实的人上手业务、排查问题、学习新框架的速度都不会差基本功虚浮的人即便简历写得天花乱坠一遇到线上偶发Crash就会手足无措。这套卷子就是按照这个逻辑设计的。2. 语言与运行时Objective-C的深层考点是真正的分水岭2.1 runtime与消息机制背下来≠理解这几乎是所有iOS校招笔试的必考区域网易的卷子也不例外。围绕runtime的题目通常有这几类向一个nil对象发送消息会发生什么、如何动态添加方法、消息转发的完整流程是什么、isa指针和class对象的关系。大部分同学都能答上来“向nil发送消息不会崩溃只是什么都不做”但再往深问一步“为什么不会崩溃整个消息发送的路径是怎样的”就开始含糊了。这里的核心知识点是objc_msgSend的执行流程方法调用本质上就是给对象发送一条消息编译期无法确定具体实现时会走“查找缓存-查找方法列表-走消息转发”的路径。我建议准备这类题时不要只背结论而是真正打断点跟一遍objc_msgSend的汇编调用或者在调试器里用class_getMethodImplementation验证一个方法是否存在。只有亲手操作过面试官追问“如果方法列表里找不到会怎样”时你才能自然地接住。2.2 内存管理引用计数和循环引用要形成条件反射网易卷面里内存管理相关的题目占比很高而且考得非常细。属性修饰符是重灾区strong、weak、copy、assign、unsafe_unretained这些词很多人背得出“strong是强引用weak是弱引用”但放到具体场景里就会踩坑。比如用copy修饰NSMutableArray你以为是为了“防止外部修改”实际上copy会把它变成不可变的NSArray之后调用addObject直接崩溃。这种题考察的不是记忆而是你有没有在真机上被它咬过。循环引用这块几乎必考block相关的引用环。面试官常给的场景是一个ViewController持有blockblock内部又使用了self如果不做处理会发生什么用__weak和__strong分别能解决什么问题。我见过的优秀回答里有人会主动提到“block对self的捕获是强引用对__weak变量是弱引用但对__strong局部变量又会变成强引用所以要在block内先weak再strong防止执行过程中self被提前释放”这个细节这种回答一下子就能和背诵型选手区分开。2.3 KVC/KVO不仅是API更是理解事件机制的门KVC和KVO在笔试里通常不会单独出大题但会以小选择题的形式混杂在runtime或UI相关题目里。比如KVO的实现原理是什么为什么说KVO是建立在runtime之上的如果你手动调用setValue:forKey:和直接给属性赋值KVO的触发时机有什么区别这些问题的背后是同一个机制KVO在运行时动态创建了子类并重写了setter方法所以只有通过setter修改属性才会触发回调直接改成员变量是不会触发的。这里有个很少人注意到的细节对同一个对象添加多个观察者时KVO的触发顺序和移除观察者时机的坑以及iOS 11之后系统对KVO的autorelease行为做了调整导致dealloc里移除观察者如果不及时反而会触发crash。笔试虽然不考这么深但准备时能想到这个层面说明你真的在工程里摔倒过。3. UI与系统机制UIKit调用链、RunLoop和并发是高频陷阱区3.1 ViewController生命周期执行顺序和最佳实践UI相关的题目里最经典的就是给你一个ViewController从创建到销毁的过程让你排列viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear、dealloc的执行顺序。这个大部分人都能排对但网易这类公司喜欢加一层“坑”在viewDidLoad里获取view的frame会得到什么什么时候frame才是最终值viewWillAppear里做哪些操作是浪费的说句实话这个坑我当年也踩过。在viewDidLoad里尝试用view的初始frame做布局结果push回来之后发现位置不对。原因是viewDidLoad只是表示视图已加载此时正处于视图层级中的位置、大小都还没有完成布局安全区域的最终值也要到viewDidLayoutSubviews或者viewSafeAreaInsetsDidChange之后才准确。面试官想看到的回答是不仅要背出生命周期顺序还要知道每个时机“适合做什么、不适合做什么”比如数据请求可以放viewDidLoad但依赖最终frame的布局必须放到viewDidLayoutSubviews并做防重复标记。3.2 RunLoop为什么面试官一提起就两眼放光RunLoop的题目在笔试卷里往往以“多选”形式出现四个选项分别描述RunLoop的工作模式、事件源、和线程的关系、以及和定时器的关系。很多人在这一步失分是因为日常开发里确实很少直接操作RunLoop最多就是NSTimer不灵了加一下NSRunLoopCommonModes。但RunLoop恰恰是理解iOS事件机制的一把钥匙。它解释了为什么滑动列表的时候定时器会暂停为什么performSelector:afterDelay会在滚动结束后才执行为什么UIImageView的渐显动画在滚动时会卡顿。要掌握这块我建议自己写一个小Demo在子线程里启动一个RunLoop然后往里面source0/source1消息看看RunLoop的退出条件是什么再把一个NSTimer分别添加到DefaultMode和CommonModes在界面上拖动滚动视图观察回调变化。这套实验做下来笔试里关于RunLoop的选择题基本是稳的。3.3 并发编程GCD死锁和线程安全并发题在网易笔试卷里属于“会者不难难者不会”的部分。最典型的考察点是在主队列同步提交一个任务会发生什么为什么在串行队列里嵌套同步提交会产生死锁吗同样的问题换成并行队列呢核心要抓住两条铁律同步提交是“等当前任务执行完再继续”异步提交是“把任务丢给队列不等”主队列本身是串行队列所以在主队列上同步提交任务等于“让正在执行任务的队列停下来等一个排在后面的任务”必然死锁。大家容易混淆的是自定义串行队列嵌套同步提交一样会死锁因为串行队列同一时刻只能执行一个任务你让队列等自己。这种题需要画图理解千万不要靠背答案。线程安全这块笔试倾向于考原子性。atomic修饰的属性是不是绝对线程安全的答案是否定的atomic保证的是读写的原子性但无法保证“先读取再判断再写入”这种复合操作的线程安全。这里有一个我在实际项目里遇到过的经典问题多个线程同时往同一个可变字典里写数据结果偶发crash崩溃信息指向objc_sync_enter。排查下来就是两个线程同时修改超出了atomic的覆盖范围。笔试遇到这类题回答时把“原子性、可见性、复合操作”三个词都点上基本就是高分答案。4. 网络、存储与架构综合题里“不难但容易翻车”的板块4.1 HTTP/TCP基础该背的还得背但别只会背网络部分在网易iOS笔试里不会缺席。常见的考点有三次握手和四次挥手分别是怎样一个过程、为什么建立连接是三次而不是两次、HTTP和HTTPS的区别、HTTPS的TLS握手流程大概是什么样的、DNS解析被劫持怎么应对。这类题低门槛但拿满分不容易因为面试官喜欢在你答完基础知识后追加一句“那你说说这在iOS开发里有什么具体应用场景”这就要求你不只是背协议还要知道它们和iOS开发的结合点比如Charles抓包为什么能解密HTTPS流量中间人是怎么植入证书的、ATS从iOS 9开始强制HTTPS后对旧接口的影响、直播或长连接场景中TCP的粘包问题怎么处理。我在笔试复盘时发现很多同学HTTP状态码背得滚瓜烂熟但问“301和302业务上会带来什么差异”就答不上来这其实才是面试官真正关心的落地点。4.2 本地存储选型看似选择题实则是架构观存储相关的题目通常不会直接让你写SQL而是给一个业务场景让你选方案用户偏好设置用什么、高频读写的小数据用什么、需要全文搜索的日记App用什么、需要加密的登录态用什么。四个选项排在那里NSUserDefaults、CoreData、FMDB/SQLite、Keychain。这个选型题很有水平因为它没有任何一个答案是“绝对正确”的关键在你说不说得出理由。NSUserDefaults适合小规模偏好设置但它会在启动时把整个plist加载进内存塞大对象会导致启动变慢CoreData适合对象关系复杂的场景但学习曲线陡、多线程环境坑多FMDB适合团队里SQL基础好、需要精细控制SQL的业务Keychain则用于敏感信息。我在项目里见过有人把几MB的缓存JSON塞进NSUserDefaults结果App启动时间直接翻倍这就是选型不当的代价。笔试里能主动说出“我会根据数据量、读写频率、安全等级和团队维护成本做选择”就已经超过了大多数人。4.3 架构设计题为什么MVC会被问MVVM的坑又在哪有些年份的网易iOS笔试会在主观题里放一道“简单设计题”比如让你设计一个图片缓存组件或者说说你理解中MVC、MVVM的区别。别小看这种题它比选择题更能反映你的工程化思维。图片缓存组件的设计关键要答出三层内存缓存NSCache、磁盘缓存文件系统、网络请求。NSCache和NSMutableDictionary有什么区别、磁盘缓存的key怎么做哈希、缓存淘汰策略怎么定、线程安全怎么保证。如果只答“用SDWebImage”就废了面试官想看的是你有没有独立设计的能力。MVVM这块很多应届生会机械地背“VM是View和Model之间的桥梁”但问到“VM里要不要import UIKit”“ViewModel和View之间的数据绑定用什么方案实现”就卡壳了。我的看法是笔试阶段不需要你有非常深度的架构理解但你至少要说清楚每一个设计模式解决的是“哪个具体的痛点”比如MVC里Controller越来越臃肿MVVM试图用数据绑定把展示逻辑从Controller中抽离但代价是调试链路变长。能够这样对比地说面试官就能判断你不是背概念的人。5. 从真题反推复习路线程序员视角的备考清单5.1 算法编程题刷题范围不需要贪多但必须刷出感觉网易这套试卷的编程题和许多大厂类似基本上是一道链表/数组操作类一道动态规划或者字符串处理类偶尔带一道二叉树。难度偏LeetCode中等极少出到Hard。但笔试的难点在于时间压力每道题不只要求能解出还要在半小时内写出无bug、能处理边界的代码。我的刷题建议是从LeetCode hot 100开始按“数组、字符串、链表、二叉树、动态规划、栈/队列”六大类各刷十道左右刷到看到题目能画出大概思路为止。链表类题目需要特别注意边界条件头节点为空、只有一个节点、要删除头节点时惯用手法是引入dummy节点二叉树是递归和层序BFS都要网易的编程题有时会要求“按层输出”这就是层序模板动态规划不要盲目开二维数组很多题可以先尝试从递归回溯改记忆化再改DP。5.2 语言进阶啃透这几本书笔试的OC部分基本无忧关于Objective-C的备考我常给周围人的建议是《Effective Objective-C 2.0》是必读最好能读两遍《Objective-C 高级编程》里“iOS与OS X多线程和内存管理”部分要精读Apple官方关于runtime的文档过一遍不要求全文背诵但要知道什么功能是由runtime提供的。读这些书的技巧是不要按章节平推而是先读“属性修饰符”“block”“内存管理”三章然后去试着手写一个带有dealloc、weak引用、block回调的Demo用Instruments的Leaks和Allocations工具看内存波动。笔试前一周再突击看“runtime、消息转发、KVC/KVO”这几章配合在Xcode里打断点调试效果好于把书抄三遍。5.3 系统框架用面试题倒查官方文档iOS系统框架的内容太多准备时容易找不到重点。我的办法是“倒查”把历年校招题里出现过的UI/系统相关知识点列出来UIViewController生命周期、RunLoop、GCD、TableView优化、事件响应链然后逐个去Apple官方文档里找对应的章节读。官方文档里都会有明确的“Discussion”部分把知识点放在具体场景里讲解。TableView优化是这里面的高频题。面试官喜欢的思路是从CPU和GPU两个角度拆解。CPU层面要避免在cellForRowAtIndexPath里做重复的视图创建和复杂布局计算提前计算并缓存行高GPU层面要避免离屏渲染比如圆角、阴影、mask不要滥用能用图片切图就切图实在需要圆角就在内容层单独做。笔试里出现这类题能答出这两个角度的人少之又少答出来就是亮点。6. 回看这份卷子时我琢磨出的名企笔试观6.1 校招筛选的本质看你能不能拆掉“模糊的墙”网易这套笔试卷给我最大的启发是它的考点并不是孤立的知识点而是一条条“从用户场景到技术实现”的拆解链路。比如KVO的题表面考runtime实质是看你能不能理解“一个属性的变化如何被系统感知并传递”GCD死锁题表面考队列实质是看你会不会在脑袋里模拟事件执行的时序图片缓存设计题表面考组件实质是看你能不能把一个复杂需求拆成若干个小模块并给出每部分的权衡方案。这种能力不是考前突击能练出来的它来自日常写代码时是否习惯性追问“这一行代码底层发生了什么”。所以准备校招的同学我特别想说一句不要只埋头刷题多在真机上做实验验证你的猜想多读优秀第三方库的源码多记录自己踩过的坑。这些经验和习惯最终都会在笔试和面试里以“手感”的方式体现出来。6.2 笔试不是终点往后每一轮都在延伸这套卷子的逻辑如果你通过了笔试卷后面的一二面技术面其实问的还是这些内容只不过从选择题变成了对话题。我曾经在技术面时被面试官追问过“你说你熟悉内存管理那在ARC下如何实现一个weak变量的自动置nil描述一下底层机制”当场就意识到笔试那点储备只是入场券。所以我的建议是在笔试前就把复习的颗粒度放细一点不要觉得“笔试不会考这么深”。你以两轮面试的深度去准备笔试笔试的通过率会高很多而且后面的面试压力也会小很多。反过来如果笔试只求压线过那面试时每一道题都会是一场苦战。6.3 最后分享一个我当时用过的笨办法准备这套卷子的时候我建了一个“错题文档”每做错一道题就复制进去然后写三段话第一段是“正确的结论”第二段是“我错在哪了”第三段是“用什么实验能验证这个结论”。复习的时候不看原题只看这个文档。这个方法很笨但确实让我的知识盲区一个个被填平了。到了后来我发现很多考题翻来覆去考的就是那些核心概念只是换了不同的壳。这套方法论后来我带新人的时候也一直在用。现在如果你正对着一堆iOS考点不知道从哪下手不妨也建一个这样的文档从runtime、内存管理、RunLoop、并发这几个最核心的模块开始把每个知识点按“结论-错因-验证方法”三栏填满。这个过程本身就是你从“背题人”变成“工程师”的转变过程。
返回列表