☰
网易iOS校招笔试题深度解析:runtime、内存管理与RunLoop考点全拆解
2026/10/24 2:32:13 网站建设 项目流程

那年九月的深夜,我在线做完网易2018校招iOS开发工程师笔试卷时,最大的感受不是题目难,而是“这套题出得真老辣”。它不考你Swift最新语法背得有多熟,也不问某个API的拼写,而是把iOS开发最核心的底层逻辑、计算机基础和你平时写代码时会不会追问“为什么”的习惯,一次性摊开来放在你面前。距离那场考试过去这么多年,回看这套题,它依然是校招iOS岗笔试题里很有参考价值的一套,尤其是如果你想进的是那种重视技术深度的大厂。

这篇内容不打算复述具体题目(毕竟网上已经能搜到原卷),而是把整套卷子按考点拆开,讲讲每类题到底在考察什么、背后对应的知识盲区是什么、以及我后来在自己带实习生的过程中,发现哪些坑是应届生最容易踩的。无论你是正在准备校招,还是打算跳槽想检验一下自己的基础,这篇都值得你花二十分钟读完。

1. 拆卷第一印象:这套题在考什么,又故意不考什么

1.1 卷面结构和考核落点

网易2018校招iOS笔试卷整体分两大块:客观题(选择题为主)和主观编程题。客观题覆盖语言基础、内存管理、UIKit、计算机网络、操作系统和少量数据结构,主观题则是标准的算法/编程实现。整体难度不是“题题致命”,而是呈阶梯状:前面有送分题,中段有需要细想才能避开陷阱的题,压轴则用来区分谁真正写过代码、谁只是背了八股。

这套题最值得玩味的是它的“取舍”。2018年Swift已经出了4.0,iOS 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持有block,block内部又使用了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、并发这几个最核心的模块开始,把每个知识点按“结论-错因-验证方法”三栏填满。这个过程本身,就是你从“背题人”变成“工程师”的转变过程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询