
把货拉拉这套2018秋招iOS工程师笔试题卷一A拿在手上的时候我第一反应是这排版真像高考卷。但翻完一遍之后反而觉得踏实——因为它没有故意出偏题怪题几乎所有题目都能从日常开发里找到影子。这套卷子对当时的应届生来说最友好的地方在于它考的是“你有没有真的写过App”而不是“你是不是把八股文背得滚瓜烂熟”。如果你正在准备iOS面试或者想看看货拉拉这类业务型公司在选人时到底看什么这篇文章就是我对这套卷子的完整复盘内容包括考点拆解、答题思路和踩过的坑希望能帮你把复习方向从“背知识点”拉到“解决问题”上。1. 这套卷子考的是什么先看整体出题思路1.1 基础语法与内存管理占比最高打开卷第A页前几道题基本都是基础语法、属性关键字和内存管理问题。这类题目表面上是送分题实际上在筛人。原因很简单一个iOS工程师如果连strong、weak、copy、assign的区别都说不清后面的UI和网络部分基本没法聊。我见过不少候选人能闭着眼说出“copy用于NSString”但让他解释“为什么可变字符串赋值给copy属性后原值变化不影响新值”就卡住了。这套卷子里的基础题问得比这更深一层它不会直接让你写关键字含义而是给你一段代码让你分析对象什么时候被释放、什么时候会崩溃。提示复习时不要只背结论一定要把每个关键字的底层语义和生命周期绑定在一起理解。比如weak背后涉及objc_loadWeak和objc_storeWeak面试官换成“weak指针怎么自动置nil”的考法你也能接住。另外属性关键字这块货拉拉的题里还出现了atomic的坑。很多人以为atomic就能保证线程安全实际上它只保证读写原子性不保证业务逻辑安全。我记得有一道题是判断一个atomic修饰的NSMutableArray在并发读写时会不会崩正确答案是“仍然会崩”。这个知识点在笔试题里很常见但很多人会答错因为它需要你理解“属性线程安全和容器线程安全是两回事”。1.2 越偏实践越能拉开差距这套卷子的第二个特点是选择题和判断题之外的简答题几乎全部场景化。比如会给你一个TableView卡顿的场景问你怎么定位和解决或者给你一段网络请求的代码问它哪里可能造成内存泄漏。这类题没有标准答案但很能看出一个人真实的项目经验。如果你只在Demo里写过列表、从来没做过性能优化答起来就会很虚。货拉拉的业务里大量依赖地图、定位和列表所以他们对“滚动流畅度”和“网络请求生命周期”这两个点特别敏感题目也围绕这些出。我当时答题时给自己定了一个原则凡是场景题不直接给结论先复述问题再给排查路径最后给方案。比如卡顿问题我会先写“先确定是主线程卡顿还是掉帧再用Instruments的Time Profiler和Core Animation工具看耗时”这个“先定位再解决”的思路比直接写“用异步加载图片”高出一个段位。阅卷人想看到的是你有没有一套处理问题的框架而不是零散的知识点。2. 内存管理从ARC到循环引用的必答题2.1 手写内存管理逻辑的考察方式2018年的时候Swift已经流行了几年但货拉拉这套卷子仍然保留了Objective-C的题目并且很大一部分集中在手动内存管理上。这不是说公司还在用MRC而是想通过这类题考察你对引用计数的理解是否透彻。卷子里有一道题是问在ARC下__weak、__strong、__unsafe_unretained修饰的变量在作用域结束时分别会发生什么。:__weak会自动置nil__unsafe_unretained不会而__strong会释放一次。如果你只是背过表格遇到“__unsafe_unretained在对象释放后再访问会野指针崩溃”这种追问就会露馅。更关键的是这道题延伸到了“容器对元素的持有”。我记得有一道填空题类似是数组里添加一个对象后数组对对象的引用计数是加一还是加二。很多人不加思考直接回答加一但其实要看调的是不是addObject:以及对象是否被额外copy。这类题我不确定原卷是不是完全一样但考点方向是明确的引用计数不是算术题它是对象生命周期的晴雨表。2.2 循环引用的判断与调试方法循环引用是iOS面试的常客这套卷子基本没绕过。最常见的考法是给一段Block内部使用self的代码问会不会造成循环引用。除了一眼看出问题的“Block持有了selfself又持有了Block”之外货拉拉的题还加了一个变化把self换成_ivar直接访问实例变量。很多人以为_ivar没有通过self访问就不会被捕获实际上Block捕获的是一个指向对象的指针在MRC里是__block或者直接捕获在ARC里是__strong捕获所以照样可能造成循环引用。更进一步如果Block里用了strongSelf weakSelf还要判断strongSelf的作用域是否超过Block生命周期。说到调试方法这一块在项目实战里特别重要。笔试里可能会问“你在项目中遇到过循环引用吗怎么检测的”我当时分享的是用Xcode的Debug Memory Graph在Debug面板里点内存节点就能看到对象之间的持有关系。如果看到一个对象被多个对象持有优先怀疑Block、Delegate、NSTimer、CADisplayLink这四类。还有一个技巧是在dealloc里打印日志如果某个对象一直不销毁日志不打印就是线索。这些经验比单纯背“循环引用的四种情况”更有说服力。3. Runtime与多线程iOS的高频深水区3.1 消息发送与转发机制货拉拉的笔试题里Runtime考得不算特别深但很刁钻。它没有直接问“消息发送的过程是什么”而是问“向一个nil对象发消息会怎样向一个没有实现方法的对象发消息会怎样”。前者是“方法调用不会崩表达式返回空值”后者会触发unrecognizedSelector崩溃。题目背后想考察的是你是否理解Objective-C的运行时动态性。如果只是背“objc_msgSend三步走”是没用的因为面试官可以继续问resolveInstanceMethod:、forwardingTargetForSelector:、methodSignatureForSelector:和forwardInvocation:分别解决什么场景的问题。我当时复习时把消息转发过程画成了一条线先查缓存再查类方法列表找不到就往上走父类最后兜底进入动态方法解析和消息转发。这套卷子有一道判断题是“消息转发到forwardInvocation:时如果连方法签名都没有会抛出异常”这句话是对的。因为methodSignatureForSelector:返回nil时forwardInvocation:根本不会被调用直接走doesNotRecognizeSelector:。这个细节平时只写业务代码的人很难注意到。3.2 多线程场景下的同步与死锁问题多线程部分卷子里出现了GCD和NSOperation问得最多的是串行队列、并发队列以及async、sync的组合。有一道题大概是“在当前串行队列里执行dispatch_sync到当前队列会发生什么”。答案很明确死锁。但笔试的考察点不只是“会不会死锁”还要你解释为什么。因为sync意味着“等当前Block执行完再继续”而当前队列正在等待这个Block执行完互相等待就卡死了。我答题时会顺手写一句“这就是为什么苹果不建议在主线程调用dispatch_sync去操作主队列”。另外多线程还和线程安全结合在了一起。有一道题是给一个count属性加锁问用什么方案。当时可选项有synchronized、NSLock、dispatch_semaphore、atomic。正确的思路是简单的读改写用锁如果对性能有要求可以用os_unfair_lock或原子操作synchronized最方便但性能一般dispatch_semaphore适合控制并发数量。这道题没有唯一正确答案关键是能不能把每个方案的优缺点说出来。在项目里我实际用过dispatch_barrier_async来处理多读单写场景如果笔试时能补充这一层会让阅卷人觉得你是有实战经验的。4. 界面与网络笔试中容易被忽略的细节4.1 视图生命周期与自动布局UI部分的题货拉拉没有考太多“用代码写一个UIView”这种而是把重点放在了视图控制器的生命周期和自动布局上。有一道题是让你写出viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear的调用顺序以及当内存警告时会被调用哪个方法。这里面最容易被忽略的是viewWillLayoutSubviews和viewDidLayoutSubviews的位置。很多应届生把布局和生命周期的顺序搞混。我当时的答题思路是先列出一个页面从创建到展示的完整调用链再重点标出自动布局触发布局子视图的时机。自动布局这块卷子问了UIStackView的实现原理。这个知识点在2018年前后正好是热点因为iOS 11刚刚把UIStackView的嵌套能力加强了不少。题目大概是想知道你是否理解UIStackView只是“管理约束”的容器而不是自己计算frame。如果你在项目里用过UIStackView会知道它会把内部视图的 translatesAutoresizingMaskIntoConstraints 自动设为NO然后统一管理约束。答这种题时把“StackView能不能解决所有布局问题”作为一个讨论点会显得思考更全面。比如复杂页面还是需要灵活使用约束优先级而不是一味堆StackView。4.2 网络层设计考察如何从Code到架构网络相关的题目货拉拉没有让你手写一套网络请求框架而是给了一段逻辑残缺的请求代码让找问题。常见的问题包括回调在子线程更新UI、没有处理弱引用导致Block持有self造成泄漏、没有取消请求导致页面销毁后回调还执行。这些点全踩过的人应该不少。我记得有一道题是问“如果用户快速点击按钮发起多个相同请求怎么防止重复请求”。比较好的方案是加请求去重逻辑比如保存一个请求队列同一URL和参数正在请求时后续请求直接忽略或等待回调。这套卷子还把网络和Json解析一起考了。它可能会给你一个JSON结构问你怎么建模。更高级一点会问如果后端返回的字段是NSNull你怎么处理这道题的坑在于直接对NSNull发消息不会崩溃但如果你用KVC去赋值给一个非对象属性就会出问题。我在项目里通常会在模型层的解析方法里统一处理空值比如写一个safeObjectForKey的category。这种经验不是背出来的是真正踩坑踩出来的写在卷面上会让后续面试官对你的项目经验产生兴趣。5. 算法与项目题怎样拿到额外分5.1 常见算法题型的代码风格货拉拉这套笔试里算法题的比例不算高但也有一两道经典题。方向集中在数组、字符串和链表没有特别偏的动态规划。有一道题印象比较深是手写一个字符串反转并且要求考虑时间复杂度和空间复杂度。很多人第一反应是倒序遍历拼字符串但用NSMutableString逐个插入会触发大量内存移动性能并不好。更合适的做法是转成字符数组后原地交换或者用reverseObjectEnumerator。这类题目真正的分差在于边界条件处理空串、只有一个字符、含有中文NSString的length和UTF-16字符数量不同。我在答题时会在代码里主动加上这些边界判断哪怕题目没有要求也能体现出严谨。另外链表的题也出现过。货拉拉的业务里很多功能模块都依赖队列、缓存链表题可以看作是对数据结构基础的考察。常见的反转链表、合并有序链表至少得能手写出来。如果你太久没写建议在LeetCode上把LinkedList分类的简单题过一遍。笔试时算法题不要求用最优解但必须保证逻辑清晰、命名合理、没有语法错误。有的阅卷人会重点看变量命名和注释是不是完整因为这代表你的工程习惯。5.2 项目描述中的STAR写法卷子最后通常会有项目经验相关的开放式问题不是让你写一篇长文而是让你用简短文字描述一个最有代表性的项目包括你的角色、难点、解决方案和最终结果。这种题在笔试里容易被轻视但它比算法题更能影响面试官对你的预判。我当时用的就是STAR法则Situation项目背景、Task负责模块、Action具体怎么做、Result结果数据。比如做一个列表优化项目不要写“我用异步加载图片解决了卡顿”而要写“在XXX业务页面用户反馈下滑掉帧我通过Instruments定位到图片解码在主线程改为在子线程预解码并缓存结果后掉帧率从XX%降到XX%”。这套卷子的项目题还有一个细节它会要求你写“你在项目中做的一个技术决策”。很多人会写“我选择了MVP架构”但如果不说清楚为什么选它、解决了什么痛点就显得很空。我当时写了从MVC转到MVVM的原因——页面逻辑太重、ViewController超过2000行可测试性差。这个“为什么选”比“用什么”更能显示你的思考深度。货拉拉这类公司业务迭代快特别需要能独立做技术选型和权衡的人项目题就是展示这个能力的窗口。6. 复盘与备考建议踩过坑后的体会6.1 时间分配和答题顺序这套卷子整体题量不算少我记得大致是选择题、填空题、简答题和算法题都有如果按部就班从第一题做到最后一题很容易在后面的大题上时间不够。我自己的经验是先快速扫一遍整张卷子把会做的题标记出来优先做简答题和算法题因为这类题分值高、主观性强即使答得不完美也能拿到步骤分。选择题和填空如果卡住先凭经验选一个在题目旁边打个问号有时间再回来看。时间分配上我是按“基础题40%简答40%算法20%”来控的。如果选择题里出现需要画图和计算的题比如引用计数变化、队列执行顺序不要心算直接在草稿纸上画时间轴准确率会高很多。货拉拉的题目偏应用不会像考研题那样控制时间到秒级但你要是因为前面犹豫太久导致最后算法题只写了一半就很亏。6.2 工程能力如何在笔试中体现最后想说一个很多应届生容易忽略的东西笔试不只是考察知识储备它还在偷偷考察你的工程能力。答题时把“代码可读性”和“异常处理”放在前面就是在向阅卷人释放信号。比如在写OC方法的实现时主动加上nil判断、dispatch_async回到主队列更新UI这些看似多余的操作反而是加分项。我当时在一道题的答案里写了“在主线程刷新UI”后来面试时面试官特意提了一句“看到你这点说明你真的上过线”。备考建议也顺带说一句不要只看《Objective-C高级编程》和GitHub上的八股文一定要自己动手把最常见的Bug复现一遍。循环引用、野指针、线程死锁、TableView卡顿这四个问题在货拉拉的笔试里几乎换着花样考。你亲手调试过一遍才能在考场上写出“为什么”和“怎么解”。我当时为了搞清循环引用专门写了个DEMO用Memory Graph看到UIViewController始终没有释放那一刻的理解比看十篇文章都深刻。我把这套卷子翻来覆去看了很多遍最大的感受是2018年的题目虽然年代感十足但核心考点到现在依然是iOS面试的基本盘。扎实的内存管理意识、对Runtime消息机制的理解、多线程场景下的边界把握、网络层和UI层的工程实践这些东西不会因为Swift取代OC而有根本改变。如果你正在准备面试别急着刷一堆偏题怪题先把这份卷子暴露出来的基本功练到肌肉记忆比什么都重要。