复盘:从内存管理到Auto Layout的考点与实战)
1. 这套题为什么值得复盘1.1 校招笔试题型与考察目标金山办公的2020校招iOS笔试题二当时在应届生圈子里传播度还挺高原因很简单它不是那种靠死记硬背就能过的卷子。整张卷子覆盖了Objective-C语言基础、Foundation框架、内存管理、多线程、网络层、UI布局以及少量的App工程化内容题型基本是单选、多选、简答加一道编程题。从考察目标来看它想筛选的不是“刷过多少题”的人而是“有没有真正写过iOS App、踩过真实开发中的坑”的人。我当时拿到这套题的第一感受是它把面试官真正关心的东西藏在了题目背后。比如一道关于block循环引用的选择题表面在考ARC下的内存管理实际是在考察你有没有在项目中遇到过self被block持有导致的dealloc不执行一道关于UITableViewCell复用的题目表面在考cellForRowAtIndexPath的写法实际是在考察你有没有处理过列表滑动卡顿和复用数据错乱。笔试只是一个入口后面面试官会根据你的答案追问问的就是这些实际场景。所以这篇文章不只是对着题目念答案而是把每一类考点背后的考察逻辑、常见失分点、以及真实项目里怎么落地都拆开讲。适合正在准备秋招或春招的应届生也适合工作一两年想跳槽、想系统梳理iOS知识体系的开发者。如果你还没到投简历的阶段提前看这篇也能帮你理清iOS开发需要掌握的核心知识脉络。1.2 从“二”这个编号能读出什么“二”说明这不是单独的试卷而是一个题库体系里的第二套。这种出题方式在校招里很常见一套题库拆成多份卷子分发给不同批次或不同岗位方向的候选人题目会有重叠但组合方式不同。拆解“二”这套题时我关注的是它与笔试一可能的差异点——第二套通常在基础上增加了更多进阶题和应用场景题。比如金山办公本身是做WPS Office的产品矩阵覆盖Windows、macOS、iOS、Android还有云端协同。这种公司的iOS笔试题不会只考UI控件和API调用它会倾向考一些日常开发中真正影响体验的点文件同步状态下的数据一致性、编辑文档时的内存占用、多任务切换时App的状态保存。这也是为什么这套卷子里有不少题目都带“场景前缀”——不是直接问“AFNetworking怎么用”而是先描述一个“用户在断网状态下编辑文档点击保存后发生什么”的场景再让你选合理的处理方案。对准备考试的人来说看懂“为什么考这道题”比“背下这道题的答案”更重要。你只有在平时开发时多问自己“这个功能在边界条件下会怎样”才能在校招笔试和面试里真正接住面试官的问题。2. 高频笔试考点逐题拆解2.1 运行时、内存管理与KVO失分重灾区iOS笔试里Objective-C的运行时和内存管理几乎是必考板块。这套题二在这方面大概占了四分之一的分值核心考点有三个消息机制、ARC下的对象生命周期、KVO/KVC的实现原理。先说消息机制。很多候选人能背出“objc_msgSend”这个函数名但题目只要拐个弯问“方法查找失败后会发生什么”就有一半人答不上来。正确路径是先查当前类的cache再沿继承链逐级查找方法列表找不到就尝试消息转发动态方法解析、备用接收者、完整转发三步全失败才抛unrecognized selector。这个链路必须完整写出来因为面试官接着就会问“你在项目里用过消息转发吗”如果你的答案是“没用过”这道题最多只能拿一半分。我在项目里处理过最多的是“为NSNull添加安全的消息转发”让数组或字典里出现NSNull时不会直接崩而是返回nil。再说循环引用。笔试里常见的考法是给一段代码问有没有问题。比如block里使用self.property即使声明了__weak如果在block内部又把这个weakSelf重新强引用依然会形成保留环。更隐蔽的是NSTimer强持有target如果你在dealloc里才invalidate那dealloc根本不会触发timer永远不释放。正确做法是在viewWillAppear或viewDidAppear里创建timer在viewDidDisappear或viewWillDisappear里invalidate并且用weakSelf包裹selector。我把这种代码在真实项目里调试过表现就是控制器的dealloc一直不调用内存一直涨除非杀掉App。KVO在笔试题里经常和“触发时机”挂钩。一道经典的变体题是在dealloc里移除KVO监听和自己手动removeObserver顺序写错了会怎样。正确理解是KVO观察者不会强持有被观察者但被观察者释放时如果观察者还注册着系统会crash。所以官方推荐在dealloc里调用removeObserver但必须保证remove操作不会触发KVO回调时访问已释放对象。更细的点是对同一个key注册两次观察者remove一次是崩溃的所以更好的做法是用统一的KVO工具类或使用Block KVO封装。注意笔试里写代码题时即使题目没有明确要求最好也画出或写出对象引用关系图。解释清楚“谁强引用了谁”“这个引用什么时候解除”比只给出代码更能体现你对内存管理的理解。2.2 UI布局与Auto Layout从UIStackView到分屏适配这套笔试题的UI部分没考太偏但有一个很有代表性的考点如何实现一个在横竖屏、不同尺寸下都能保持间距一致的布局。当年笔试题里给了4个选项分别是手动计算frame、Autoresizing Mask、Auto Layout、UIStackView。选UIStackView的不一定对因为题目还加了一个前提——需要支持iOS 11及以上版本。很多候选人没意识到UIStackView虽然在iOS 9就引入了但早期的UIStackView在动态增删子视图、嵌套布局时性能并不好而且它在iOS 11之前对隐藏子视图的处理不够完善。如果App最低支持版本是iOS 11那么UIStackView确实是最优解如果最低支持版本更老就要考虑用Auto Layout加约束优先级来模拟StackView的行为。这就是为什么我说“选框架要结合最低支持版本”而不是“哪个新选哪个”。还有一个隐藏考点是分屏适配。2020年iPadOS已经支持多窗口和分屏所以金山办公出这道题是在考察你是否有iPad适配经验。在iPad上做分屏布局不能再写死宽度必须使用Size Classes配合TraitCollection来做响应式布局。我做过一个文档阅读器在iPad上分屏宽度只有320pt时工具栏上的按钮要自动折叠成“更多”菜单实现方式就是根据horizontalSizeClass和宽度做动态判断。关于Auto Layout性能笔试简答题可能会问“约束多会不会影响性能”。正确的思路是约束的构建和计算成本主要在第一次layout时频繁修改约束引起的layout pass才是性能瓶颈。优化手段包括只更新变化的约束用IBOutlets持有需要变化的约束引用而不是每次都通过遍历找到它、对列表项使用固定高度、避免在layoutSubviews里频繁修改约束。记住不要在大列表里创建太多Auto Layout约束有时候“某几个元素用frame其余用Auto Layout”混合布局反而更快。2.3 并发与网络GCD、HTTPS与ATS跟并发相关的考点这套卷子主要集中在GCD的几个核心问题上队列类型、死锁、线程安全。题目直接问“在主队列上同步执行一个任务会怎样”答案是死锁。这个例子很经典但我在实际评审代码时发现很多初级开发者只是背了结论没真正理解死锁产生的条件串行队列 同步任务 当前正在执行任务的队列就是目标队列。理解之后你就知道不只是主队列任何串行队列里嵌套同步派发到自身都会死锁。另一个更隐蔽的坑是“使用dispatch_async到主队列但在主队列任务里又去等待一个信号量而信号量由另一个串行队列的任务触发那个串行队列的任务又在等待这个主队列任务”——多队列互相等待也会死锁这种场景在搭建路由跳转等待层时容易遇到。网络部分的高频考点有三块GET与POST的语义差别、HTTPS的握手流程、App Transport SecurityATS配置。在2020年的时候ATS几乎已经是强制项笔试题会问“如果服务器只支持HTTP在Info.plist里怎么配置”。正确做法是使用NSAppTransportSecurity的NSExceptionDomains只对特定域名开放HTTP而不是全局关闭ATS。但这里还有一个坑即使是配置了domain exception如果是自签证书默认也会失败必须配置NSExceptionAllowsInsecureHTTPLoads为YES或者是用NSURLSession的delegate方法实现更细粒度的证书校验。笔试里还可能会出现URLSession和NSURLConnection对比的题。这个基本是老题了答案就是NSURLConnection在iOS 9后被标记废弃NSURLSession才是官方推荐。但深层考点是NSURLSession支持后台传输、断点续传、共享cookie存储这些能力对于一个文档类App至关重要——用户在编辑完文档后很可能切到后台上传任务还要继续执行这就必须用NSURLSession的background session。如果笔试题里描述了一个“用户切到后台文档继续上传上传完成后发送本地通知”的场景你要立刻联想到background session和background tasks。3. 笔试中容易失分的边界题3.1 多任务、后台与电量优化金山办公的App有很多后台使用场景比如打开文档后切到其他App查资料再切回来。所以这套题的简答题部分特意出了一道“App进入后台后哪些操作会被系统限制”的题目。这道题每年都有大量考生答不完整或者把“后台无限执行”当作理所当然。正确答案要覆盖几个层面第一App进入后台后只有短暂的时间现在约30秒可以继续执行代码需要在applicationDidEnterBackground里做好状态保存第二如果需要更长时间要用beginBackgroundTaskWithExpirationHandler申请后台时间但系统不会保证给多少超时后必须立即结束第三对于音频播放、定位、VoIP等特定场景可以声明对应的UIBackgroundModes但滥用会被拒审。如果笔试里的场景是“用户切后台文章朗读继续播放”那这种场景可以声明audio模式如果是“用户切后台下载任务继续下载”那要用NSURLSession的background configuration。电量优化是这套题比较超前的一个考点。2020年iPhone已经支持低电量模式Low Power Mode系统会限制后台刷新和部分动画效果。笔试的考察点是你开发的App要如何感知低电量模式并关闭非必要功能。代码上就是监听NSProcessInfoProcessInfo的lowPowerModeEnabled和PowerStateDidChangeNotification。我在做视频类App时在低电量模式下会自动关闭自动播放、降低帧率、暂停预加载实测能明显降低掉电速度。一个平时不关注系统状态的开发者很难答出这种考点。3.2 系统状态与BLE外设交互的陷阱这套笔试题里有一道比较偏的题目问的是“CoreBluetooth里系统级蓝牙状态和App级蓝牙状态如何区分”。这道题当年考的应届生很多都懵了因为它不是常规iOS面试题但却是智能硬件类App开发中会真实遇到的问题。系统级蓝牙状态指的是手机蓝牙开关是否打开通过CBCentralManager的state属性判断。App级蓝牙状态指的是你的App是否有权限使用蓝牙以及在蓝牙开关变化后App内部的业务状态。比如系统蓝牙关闭后CentralManager会回调poweredOff但你的App里正在连接的peripheral对象并不会自动消失需要你主动更新UI并处理重连逻辑。更隐蔽的是用户去设置里关闭了“允许App使用蓝牙”的权限系统会回调unauthorized状态但不会弹系统弹窗很多开发者没有处理这个状态导致App显示“蓝牙已连接”但实际收不到数据。与BLE相关的坑还有个经典场景连接多个外设时只保留一个活动连接。CoreBluetooth允许同时连接多个外设但实际设备资源有限建议连接数不要超过同时支持的最大值。笔试题里如果问“如何控制必须连接完成一个设备后才连接下一个设备”正确答案是维护一个连接队列在一个centralManager:didConnectPeripheral回调后再调用connect下一个peripheral。我在一个手持扫码设备项目里用过这个思路稳定性和性能都比并发连接好几个外设要好。3.3 App签名、证书与上架流程校招笔试题很少直接考证书和上架流程但金山办公这套题确实出了相关简答题原因可能是他们iOS团队要招能独立负责上线流程的人。我在复盘时觉得就算笔试不考这一块面试也很容易被追问值得认真准备。核心考点有三个。第一开发证书和发布证书的区别开发证书用于模拟器和真机调试发布证书用于构建上传App Store或企业分发两者都关联Bundle Identifier和团队ID。第二描述文件Provisioning Profile的作用它把证书、设备开发阶段和App ID绑定在一起App安装时系统会校验签名和描述文件是否匹配且有效。第三App Store上架流程构建上传用Xcode Organizer或Transporter上传后在App Store Connect配置版本信息、截图、审核备注然后提交审核。笔试时最容易丢分的是概念混淆。例如开发证书过期了能不能继续真机调试答案是设备上的App会闪退因为签名校验失败描述文件里注册的设备列表发生变化时需要重新生成描述文件并重新签名。还有证书吊销后之前通过TestFlight安装的App还能不能用——能用因为TestFlight验证的是Apple服务器签名不是开发者证书。这些都是真实开发中会遇到的情况如果只是背流程不看原理很难答对变体题。我建议准备校招的同学把这个流程亲手走一遍注册一个付费开发者账号或者学校能给的教育优惠从头创建一个项目配置签名跑真机再走一遍Archive和上传。这个过程会踩很多坑比如Profile不匹配、证书在Keychain里丢失、导出ipa时签名选错。但走完一遍之后关于签名和上架的所有笔试题目基本都挡不住你了。4. 从笔试题到面试如何把答案讲成亮点4.1 架构模式与混合开发方案笔试的最后一题通常是设计题或开放题给你一个“实现XX功能”的需求让你画架构图、写核心代码。金山办公这套题二的压轴题很有代表性让考生设计一个“多人在线协同编辑一个文档”的功能要求支持冲突处理、网络状态变化和离线缓存。很多考生看到这道题会先懵因为自己平时没做过协同功能但面试官其实不是要求你把功能完整实现出来而是想看你有没有基本的架构思维和信息论储备。我的建议是答题时先明确几个关键决策使用WebSocket还是HTTP轮询、冲突解决用OTOperational Transformation还是CRDT、离线缓存用本地数据库还是文件快照。你需要讲清楚每种方案的优缺点以及你根据场景选择的原因而不是盲目堆技术名词。混合开发方案也是金山办公这类公司比较关注的方向。他们的App可能有大量页面由前端用H5实现iOS侧做壳工程。笔试或面试常问“你了解哪些混合开发方案为什么选择WebView而不是React Native或Flutter”。我的理解是如果页面以展示型内容为主、更新频率高用H5合适如果页面交互复杂、需要高性能就用原生或Flutter如果团队历史包袱多可能用React Native兼容两端逻辑。关键是你能说清楚“WebView和原生通信的机制是什么”——JSBridge原理、WKWebView的message handler、URL拦截和JavaScriptCore注入这些最常考。在做架构类设计题时我比较推荐的回答框架是先描述清楚需求和使用场景再围绕场景定技术选型接着画出一张模块拆解图分层展示层、业务层、数据层、网络层最后用几句话说明数据流转路径。面试官想听到的是“决策过程”而不是“一个完美的最终方案”所以你要敢做取舍敢说“这里我选择牺牲实时性换取更低的实现成本”。4.2 用自动化与工程化能力拉高印象分虽然2020年的笔试题没直接考自动化测试但我在复盘这套题时发现简答题里有一道“你怎么保证你写的代码质量”的开放题答得好不好非常影响综合评价。我见过不少候选人只会答“我写完会自测”“我加日志调试”这种答案和没答一样。更好的思路是往工程化方向靠单元测试、UI测试、静态分析、CI/CD流水线。比如谈到iOS测试你可以讲XCTest里如何对网络层写mock测试用OCMock或者自己写Protocol做依赖注入你可以讲XCTest UI测试在自动化回归中的适用性和弊端——“UI测试不稳定真机执行慢所以只在关键路径上覆盖”。如果你用过fastlane可以讲讲它的match、scan、beta这些action对证书管理和自动化打包的帮助有多大。面试官听到你熟练使用这些工具对你的评价会从“会写功能”提升到“能独立负责一个模块的质量和发布”。还有一个很加分的点是你对构建流程有理解。很多应届生只会点Xcode的Run不知道怎么打Debug和Release的差异不知道Archive和Export的区别。如果笔试题或面试提到“为什么模拟器上的App不能直接分发”正确的答案是模拟器构建的是x86_64架构的Mach-O真机需要arm64且模拟器包不包含完整的App签名信息。如果你还能提前了解一下“我现在这个项目用了CocoaPods未来想迁移到SPM”就能和面试官聊很长时间。工程化的本质是降低协作成本和发布成本而不只是用几个工具。5. 复习时间线、资料清单与我的心得5.1 三个月复习规划参考如果你现在还有八九周就要参加校招笔试我建议按三个阶段来准备。第一阶段前三周打基础把《Objective-C编程》和《Effective Objective-C 2.0》快速过一遍重点看内存管理、block、GCD、RunLoop这几章把UIKit的常用控件和Auto Layout体系过一遍不要求能默写所有API但要理解布局机制和生命周期。第二阶段中间四周刷题加写Demo搜集最近三年的iOS校招真题按知识点分类刷每道题都要弄清楚为什么对、为什么错同时每天抽一小时写一个完成度比较高的小功能比如“拍照并裁剪上传”“实时音视频聊天房间”把刷题时学到的技术点真正用出来。第三阶段最后两周模拟面试和复盘找个朋友互相问iOS问题或者自己对着录音设备练“讲清楚一个架构设计”把之前做过的Demo整理成项目和作品集梳理每段代码解决了什么具体问题。这套题二的难度大概在中等偏上覆盖的知识面比大多市面上流传的iOS面试题集要宽。我的建议是不要只背题而是把每一道题当成一个知识树的根节点向上追原理、向下追实现、旁支追场景。比如一道“UITableView卡顿怎么优化”的题你要能向上扯出RunLoop和屏幕刷新机制向下能说出估算高度、异步绘制、图层混合等优化手段旁支能聊到SDWebImage怎么管理图片缓存。能说成这样笔试面试都不会差。5.2 我踩过的坑和一点个人心得我复盘这套题的时候想起自己当年准备校招时踩过的一个坑过度看重“冷门偏题”把大量时间花在钻研Core Animation的底层渲染和音视频解码这些知识上结果基础题反而因为手生丢了分。后来我带实习生时发现很多人也会犯同样的错总觉得考官会出偏题压分实际上笔试题的区分度主要靠“基础题你是否掌握得足够扎实”和“场景题你是否能形成自己的判断”。另一个坑是“看得多、写得少”。看别人的iOS面试题解析、刷LeetCode和算法题确实有用但它替代不了你亲手写代码。金三银四秋招季我见过太多候选人简历上写着“熟悉iOS内存管理”但真让他处理一个循环引用崩溃半天定位不到是block还是delegate的问题。建议你除了笔试准备一定要亲手维护一个自己的Demo项目定期加功能、换架构、写测试遇到问题用真机调试、用Instruments看内存和CPU这样才能在笔试和面试时给出有底气的答案。最后校招只是职业生涯的起点。就算某套笔试题没答好也没关系把错题整理成自己的知识库比拿一个offer更有长期价值。金山办公这套题二给我最大的启发不是那些考点本身而是让我意识到iOS开发是一个“场景驱动”的领域掌握了再多的API脱离真实场景都记不牢。真正有效的学习方式是拿一个真实需求从方案设计到编码实现再到上线维护完整走一遍。这个过程积累下来的经验和判断力才是通过笔试、通过面试、以及未来在团队里立足的根本。