十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

欢聚时代iOS校招B卷解析:内存管理、多线程与架构设计考点全梳理

欢聚时代iOS校招B卷解析:内存管理、多线程与架构设计考点全梳理 2017年秋招季我印象里欢聚时代的iOS工程师B卷是当时几家大厂里最“规矩”的一套题。没有偏题怪题没有强行考察源码细节绝大部分内容都落在iOS开发者的日常知识体系内但想拿高分也不容易——它考察的不是“会不会用某个API”而是“知不知道底层原理、能不能权衡取舍”。那会儿iOS开发正处在从MRC向ARC彻底过渡的阶段Swift刚出到3.x很多公司校招笔试仍然以Objective-C为主这套B卷就是典型的OC风格题目同时夹杂了少量架构和算法题。现在回看这套题对准备iOS校招的同学依然有很强的参考价值内核考点没怎么变只是在时代背景下多了些历史感。我之前在带实习生和做面试官时也经常拿这套题的变体来考察候选人。如果能把这套题吃透基本功基本就过关了。下面我把这套B卷涉及的考点、典型题目和答题思路拆开讲清楚同时补一些我在实际开发和面试中踩过的坑。准备秋招的朋友可以直接对照查漏补缺。1. 试卷整体结构与考察重点1.1 题目类型与分值分布这套B卷的题型比较常规总体分为四类选择题、填空题、简答题和编程题。我记得选择题大概10道每题有单选也有多选多选是真正的丢分重灾区因为选错一个选项整题就是零分。填空题主要考Objective-C的语法细节和Runtime相关的概念。简答题大概4道每道题需要展开论述比如内存管理、网络请求流程、多线程方案对比。最后有两道编程题一道偏算法一道偏iOS实际应用场景。分值分布上基础知识和Advanced部分各占约三成剩下四成集中在多线程、网络和架构设计上。这个比例也反映了当时互联网公司对iOS工程师的期望不仅会写界面还要能处理好并发、网络和代码组织问题。1.2 从B卷看欢聚时代当时的技术栈倾向从题目能反向推出团队的技术倾向。欢聚时代旗下产品以直播、语音互动为主这类App对性能和稳定性要求极高。因此B卷里对内存管理、卡顿优化、网络异常处理这些方向的考察会比较侧重。我记得有一道简答题问的是“直播类App中消息列表可能出现哪些性能瓶颈怎么优化”这道题看似开放实际考察的就是对CADisplayLink、异步绘制、图片解码、复用机制这些知识的理解。另外当时欢聚的iOS客户端已经在做组件化和Hybrid方案所以题目里也出现了“如何设计一个可动态更新的页面模块”这类问题。这提醒我们复习时不仅要看iOS基础还要关注大厂在规模化阶段遇到的实际问题。2. iOS基础与Objective-C必考题解析2.1 内存管理MRC与ARC的关键差异B卷里有一道经典的填空题在ARC环境下以下代码是否存在内存问题为什么。给了一段使用__weak修饰的block捕获变量的代码。很多同学一看到weak就觉得没问题但实际上如果在block内部长时间持有这个weak对象而对象在外部被释放就会变成野指针错误。解答这类题首先要认清ARC不是垃圾回收它只是编译器帮你插入retain/release。__weak虽然不会增加引用计数但也不能保证对象一定存活。如果业务逻辑要求block内必须安全使用对象还是应该用__strong在block内重新持有或者用防悬挂的包装方式。我当时在做这道题时特意写了注释来说明“weak strong dance”的用法外部weak引用进入block后先转成strong保证执行期间对象不被释放执行完再置nil。这是面试官很爱听的细节也能体现你对内存管理的理解不是死记硬背。2.2 属性关键字与线程安全陷阱另一道选择题涉及atomic与nonatomic的区别以及是否所有属性都适合用atomic。正确答案自然是atomic只能保证读写原子性不能保证线程安全而且性能开销大日常UI属性基本都用nonatomic。但B卷的陷阱在于它把场景转到了“数组属性”。题目问一个atomic的NSMutableArray属性在多线程下addObject是否线程安全。答案是不安全。atomic只能保护getter/setter方法的取值和赋值操作而addObject是修改数组内部内容整个过程不是原子的。正确的做法是加锁或者使用线程安全的容器。这里我补充一个实际经验很多初级开发者会迷信atomic以为加上就安全了。实际上就算属性是atomic如果你在block里同时读取和修改这个数组依然会崩溃。真正稳妥的做法是明确数据流的走向在关键访问点使用同一把锁。2.3 Runtime与消息传递机制Runtime几乎是iOS笔试的必考内容。B卷的简答题里有一道Objective-C中消息发送的完整流程是什么样的如果方法不存在会怎样。这个问题需要你从objc_msgSend开始讲依次是查找类对象的方法缓存、方法列表、继承链以及最终的动态方法解析和消息转发机制。回答技巧是把流程分成三块快速查找、慢速查找、消息转发。快查是查缓存慢查是遍历方法列表转发则包括resolveInstanceMethod、forwardingTargetForSelector、methodSignatureForSelector和forwardInvocation。另外要提一下NSObject的doesNotRecognizeSelector触发崩溃。我建议在回答时画一个简单的流程图文字描述即可并且举一个实际例子比如在实现一个轻量级路由时利用消息转发处理未实现的方法。这样能证明你不是背概念而是真的用过Runtime。3. UI与多线程考察3.1 界面布局AutoLayout性能与约束优化B卷选择题里有一道关于AutoLayout的在TableView滚动时什么因素会导致滑动卡顿如何优化。选项涉及到约束计算量、frame计算、离屏渲染、圆角裁剪等。这道题其实是在考察你是否理解AutoLayout在layoutSubviews时需要解线性方程约束越多、层级越深计算成本越高。正确的优化方向是减少视图层级、优先使用系统layoutMargins、避免复杂的约束优先级冲突、对于固定不动的头像或标签直接用frame或预布局。更关键的是不要在TableViewCell里动态添加大量子视图并频繁更新约束应该尽量复用模板。我记得这题后面还跟了一个小问为什么使用圆角会导致卡顿。原因是cornerRadius配合masksToBounds会触发离屏渲染。如果列表需要大量圆角头像建议使用贝塞尔曲线裁剪或者直接让美术出图。3.2 GCD与NSOperation多线程方案怎么选简答题部分有一道“对比GCD和NSOperation各自适用什么场景”。这是一道老生常谈的题目但B卷增加了难度的方式是加了一个限定条件在项目中你需要随时取消一个耗时任务你会选哪种方案。如果你只回答“NSOperation可以取消GCD不可取消”只能拿一半分。深入回答应当是GCD中的dispatch_block_t也可以取消通过dispatch_block_cancel配合dispatch_block_create但只能取消尚未执行的任务如果任务已经在执行block内部需要主动检查取消标记。而NSOperation封装了更完善的取消机制并提供依赖关系、KVO等能力适合构建复杂任务编排。当时我答题时还补充了实际项目中的选择策略简单的并发异步用GCD需要任务依赖、取消、最大并发数精细控制用NSOperationQueue。这套逻辑放到今天依然适用。4. 网络与存储考点4.1 HTTPS连接流程与中间人攻击防范B卷的简答题里有一道简述HTTPS的握手流程以及如何防范中间人攻击。这道题对于当年很多人来说比较有区分度不光是背诵CA证书链还需要说清楚非对称加密交换密钥、对称加密传输数据的过程。我的回答思路是客户端与服务端先进行TCP三次握手然后TLS握手服务器发送证书客户端验证证书可信后生成随机密钥用服务器的公钥加密发送给服务器服务器用私钥解密得到对称密钥之后双方用对称密钥加密通信。中间人攻击的关键在于证书验证环节如果客户端不做严格的证书校验攻击者可以伪造证书。所以iOS开发中需要开启URLSession的challenge回调对服务器信任进行评估不要简单调用SecTrustEvaluateWithError就放行。我补充一个常被忽略的点很多App会内嵌证书做SSL Pinning但证书过期会导致全部请求失败。B卷虽然没有直接考但我在面试中经常追问这个希望同学能了解CA信任链和Pinning的区别。4.2 数据持久化方案选型选择题问以下哪些持久化方式适合存储大量结构化数据并支持条件查询。选项包括NSUserDefaults、NSKeyedArchiver、SQLite、Core Data。正确答案是SQLite和Core Data但很多人容易漏选Core Data认为它效率不高。事实上Core Data底层也可以使用SQLite作为存储并且提供了对象管理功能对于复杂模型关系的操作有优势。不过如果团队里没有很好的Core Data封装直接使用FMDB或WCDB会更直接。这道题的价值在于考察你的工程判断力。我当时在答案里特别标注了如果只想存用户偏好设置用NSUserDefaults缓存少量对象用NSKeyedArchiver需要跨平台迁移或大数据量查询优先SQLite。这种分场景回答让面试官觉得你有真实项目经验。5. 架构设计题不仅仅是MVC5.1 从MVC到MVVM的演进B卷的最后一道架构题是现有项目中ViewController非常臃肿请提出至少两种重构方案并对比优劣。这是典型的“如何梳理业务代码”题目。大部分考生会顺理成章地写MVVM但好的答案应该先分析MVC在iOS中的实际困境View和Controller耦合紧密Model缺少主动反馈机制。我的方案是先做代码分层把网络请求、数据解析、业务逻辑从Controller抽到Service或Manager层再引入MVVM通过ViewModel暴露属性Controller只负责绑定和跳转。如果没有响应式框架可以通过Block或Delegate做绑定注意ViewModel不要直接持有View。在回答中我提到不要为了架构而架构。MVVM会增加代码量如果团队对Block/闭包不熟反而可能引入循环引用和调试困难。有效的重构应该从最臃肿的页面开始逐步替换而不是一次性推翻重写。5.2 组件化与模块通信设计还有一道附加题在一个大型App中如何实现模块间解耦避免互相引用。这实际上就是组件化问题。我给出了三层思路第一层是中间件所有模块通过URL或Protocol向中间件注册第二层是依赖注入模块初始化时通过Configuration对象传入依赖第三层是模块内聚每个模块提供明确的对外接口内部实现细节尽量不暴露。当时我还提到一个关键点组件化不只是“把代码拆成多个pod库”还需要考虑组件之间的通信方式、页面跳转路由、数据模型共享和日志上报。如果做不好这些配套机制拆出来的组件会变成一个相互import的“大泥球”。6. 算法与实际工程结合题6.1 链表反转与环形检测B卷的编程题不算难第一道是反转单链表。很多人能写出迭代版本但递归版本容易出错。我建议两种都要会并理解递归函数的返回值含义。迭代法用三个指针pre、cur、next一轮一轮翻转递归法则要先找到尾节点作为新头然后回溯时修改next方向。这道题虽然简单但高分的关键在于边界条件空链表、只有一个节点、链表有环需要加结束条件。我当时在答题时注明了测试用例面试官后来反馈说这种工程意识很加分。6.2 字符串翻转与字典序处理第二道编程题是给定一个字符串将其中每个单词翻转但单词顺序不变。比如“hello world”变成“olleh dlrow”。这道题考察的是原地操作和边界判断。常见做法是先以空格为分隔符进行单词拆分然后对每个单词做双指针翻转。这里有个坑不要用componentsSeparatedByString:后拼接因为这样会丢失连续空格。正确解法是遍历字符串识别单词起始和结束位置只在单词区间内做反转操作这样能保留原始空格。这种思路体现的是“对数据敏感度”也直接对应到iOS开发中处理富文本或输入框格式化的场景。7. 实战经验答题套路与避坑指南7.1 笔试中经常被扣分的小细节结合这套B卷我总结几个批卷时常见的扣分点。第一选择题只要拿不准就少选尤其是多选题避免错选导致零分。第二简答题不是写得多就得分要有结构先回答是什么再讲为什么最后补充实现方案。第三代码题一定要写注释最好在开头写清楚思路哪怕代码不完整也能拿过程分。还有一个小细节题目要求“请说明原因”时不要只写结论。比如问为什么block会循环引用你需要写清楚self被block持有block又被self持有形成引用环。只回答“会循环引用”是几乎不得分的。7.2 时间分配与检查策略B卷整体时间大概是120分钟我的建议是选择题控制在20分钟以内填空题10分钟简答题45分钟编程题30分钟最后15分钟检查。很多人容易在简答题上花太多时间导致编程题来不及写。编程题即使不能完整跑通也要把核心逻辑表达清楚不要留白。检查时先看有没有漏题再看多选是否误选了不确定项最后快速过一遍代码题的变量命名和边界条件。当年我就因为编程题没有判断nil而白白丢了两分至今记忆犹新。7.3 这套题对现在的启发虽然距离2017年已经过去很久但这套B卷考察的核心能力并没有过时内存管理、多线程、网络、架构设计依然是iOS面试的主旋律。变化在于现在会更倾向于考察Swift、SwiftUI和跨端方案但底层原理——RunLoop、Runtime、内存布局——仍然是区分优秀工程师和普通工程师的分水岭。如果你正准备校招与其刷各种偏题怪题不如把这份经典考点列表认认真真过一遍再对照项目经历想清楚每个技术选型背后的原因。能做到这一点不管未来面试形式怎么变你都能从容应对。我个人在实际带团队时还喜欢多问一句“你在项目中遇到的最棘手的Bug是什么怎么排查出来的”这道考题不在纸上却比任何笔试题目都更能看出一个工程师的深度和责任感。希望这份B卷解析对你的秋招准备有实际帮助也欢迎你在复习中有不同见解时和我讨论。
返回列表