拓冰建站拓冰建站
首页 / 资讯中心 / 正文

2023小满春招iOS笔试复盘:考点解析与避坑指南

看到“2023年度小满春招iOS研发岗第二批笔试”这个标题我第一反应是又一批同学要被基础题和开放题混合双打了。把完整试卷拿回来逐题过了一遍之后我的判断是这张卷子难度没有第一批高但考得更“活”选择题里全是平时写代码最容易含糊过去的细节编程题和设计题则直接考察工程落地能力。与其说它在筛基础不如说它在筛“有没有真正用脑子写过iOS代码”的人。下面我把整张试卷从头到尾拆一遍顺便把每个考点延伸出来的知识边界和踩坑点都补齐这份复盘对准备春招或者实习面试的人都有参考价值。1. 笔试整体设计与考点分布分析1.1 题型结构与时间分配这批笔试一共五大题组总分100分考试时间120分钟。我拿到的卷面结构是这样的题型题量分值建议用时单选题15题30分25分钟多选题5题15分10分钟简答题4题20分35分钟编程题2题20分35分钟设计题1题15分15分钟从时间分配就能看出来出题人没打算让你在选择题上纠结太久反而给简答题和编程题留了空间。真正的分水岭在后面前面30分选择题属于“基础过滤网”后面70分才是拉差距的地方。单选题和多选题覆盖的内容大致是Objective-C与Swift语言特性、ARC内存管理、GCD多线程、KVC/KVO、Runtime基础、Runloop常见场景、UIKit布局与响应链、网络层与数据持久化。前面几题纯粹是语言基础中间五六题开始上升到“底层原理理解”最后两三题已经涉及性能优化和系统框架了难度有阶梯不是从头难到尾。1.2 考点热度与出题逻辑我把试卷里所有题目涉及的知识点拉了一个清单再对比了一下近几年校招和社招笔面试的频率发现这批笔试有几条明显的出题逻辑。第一基础原理题占比接近一半但考的不是死记硬背。比如“ARC下__weak修饰的变量在对象释放后会发生什么”“以下哪种写法会造成block循环引用”这类题表面考语法实际考你有没有理解引用计数的底层机制。这类题如果只是背过八股看到变体就容易懵。第二系统框架题明显增加而且往深了挖。CoreBluetooth、分屏适配、电池优化这些以前社招才常问的东西这次笔试里都出现了。说明招聘方对候选人的要求已经不是“能把界面搭出来”而是“能处理系统级能力和硬件协同”。第三混合开发与生态协同的东西没有直接出大题但在选项里反复出现。UIStackView在动态布局里的表现、H5与原生通信的边界问题、Charles抓包验证请求链路这类内容都是从工程实践里提炼出来的纯粹看官方文档反而准备不到。第四设计题是开放性的没有标准答案。它考的是你对一个具体业务场景的拆解能力包括技术选型、架构分层、性能优化、异常兜底。这部分没有三四个月真实项目积累临时抱佛脚很难出效果。2. 核心基础考点深度解析2.1 内存管理与运行时原理这批试卷里内存管理和Runtime加起来出了六道题左右是单选和多选里占比最高的一块。其中一道比较有代表性的题是这样的给定了一段在block内部使用weakSelf之后再使用strongSelf的代码问这段处理主要解决了什么问题。正确的理解是如果只在block里用weakSelf在多线程环境下对象可能在执行过程中被提前释放导致后续代码拿到nil所以需要在block内部用strongSelf把对象持有住保证执行期间对象存活。这就是经典的weak-strong dance但只答出“防止循环引用”还不够还得说出“防止执行过程中对象被提前释放”。还有一道问的是消息发送流程选项里混了“isa指针查找”“方法缓存在class_rw_t里”“消息转发三次机会”这些表达。这类题想拿满分需要对objc_msgSend的完整流程有清晰认识先查缓存再查当前类的方法列表找不到就沿继承链往上找还找不到就进入动态方法解析、消息转发”这两条救火通道。我在实际调试中见过不少因为方法名拼错导致的unrecognized selector崩溃其实就是这个方法查找链路走到了死胡同。Runtime这部分延伸出去还有一个高频考点方法交换Method Swizzling。笔试里没直接考实现代码但多选里有一题问“以下哪些场景适合用Swizzling”正确选项是统计页面曝光和全局埋点这类横切逻辑不适合的是业务数据计算这类核心路径因为Swizzling会全局影响出问题极难定位。我自己的习惯是不到万不得已不做Swizzling如果做了一定要保证幂等避免重复交换导致方法递归调用。2.2 多线程与并发陷阱GCD的题这次出了两道一道单选、一道多选。单选非常有代表性在串行队列里调用dispatch_sync传入当前队列会发生什么答案是死锁。原因很简单同步派发会阻塞当前线程等待任务执行而任务又排在当前串行队列的队尾当前线程被自己阻塞队列里的任务永远等不到执行机会。这个经典例子在面试题里出现频率极高但笔试里还有一道变体如果在主队列调用dispatch_sync会怎样很多人只记得“主队列同步会死锁”却说不清楚原理这道题就是在考原理。多选那道题考的是线程安全的实现方式涉及synchronized、NSLock、信号量、串行队列、原子属性。比较容易漏选的是“串行队列读写”因为很多人写多线程只想到锁没想到GCD的栅栏函数和串行队列本身就是天然的线程安全方案。我在项目里处理共享资源的读写时经常用并发队列加栅栏函数来实现多读单写性能比全局加锁好不少。这块还有个延伸考点是iOS开发中的电池优化。试卷简答题里有一道是问“如何减少App的耗电”很多人的第一反应是定位和后台刷新。实际上高频的CADisplayLink刷新、多余的CoreLocation精度申请、长时间不休眠的Timer、大文件频繁读写这些才是耗电大户。我的建议是定时器尽量用DispatchSourceTimer替代Timer定位服务按场景切换精度能不用后台模式就不用。2.3 UI布局、UIStackView与响应链UIKit布局相关的考点这次集中在一道关于UIStackView的题上。题目问的是UIStackView相比手动约束有哪些优势以及哪些场景不适合用。优势很好答自动管理子视图的布局、支持嵌套、适配动态内容时减少约束代码量、配合隐藏和显示子视图能自动调整布局。但“不适合的场景”才是出题人真正想看的比如需要高度自定义的复杂重叠布局、对性能极敏感的列表项Cell、需要精确控制约束优先级的场景这些情况下UIStackView反而会成为束缚。我踩过的坑是在UITableViewCell里使用嵌套过多的UIStackView滚动时明显感到掉帧。原因是UIStackView本质上还是帮你生成约束嵌套深了约束数量爆炸布局计算成本升高。正确的做法是列表页尽量用手写约束或者系统原生AutoLayoutUIStackView留给页面级动态布局更合适。响应链相关的一题给了几个点击事件处理的选项问哪些说法正确。核心是理解hitTest和触摸事件的传递顺序触摸事件先由系统发送给UIApplication再传给UIWindow然后通过hitTest找到最合适的视图之后事件沿着响应链从该视图向上传递直到被处理或丢弃。这里常考的一个点是如果父视图的isUserInteractionEnabled为false子视图能不能收到点击事件答案是不能因为hitTest在父视图就已经返回nil了。还有一个点是通过addTarget添加的UIControl事件和重写touchesBegan之间的关系很多人混淆了这两个机制是共存的UIControl事件实际上是在touchesBegan之后由内部机制触发。2.4 系统框架与硬件能力蓝牙、分屏与推送这次笔试让我比较意外的是出了一道CoreBluetooth相关的简答题系统级蓝牙状态和App级蓝牙授权状态能区分吗怎么区分这是一个平时大家根本不会注意但一旦遇到系统弹窗问题就非常头疼的点。系统级蓝牙状态指的是设备蓝牙开关是否打开通过CBCentralManager的state属性判断它是CBManagerState类型有poweredOn、poweredOff、unsupported等状态。App级授权状态指的是用户是否允许当前App使用蓝牙在iOS 13之后通过CBManagerAuthorization枚举来判断二者是完全不同维度的状态。很多人在App里只判断了state poweredOn没有检查authorization状态结果用户关闭了蓝牙权限之后回调里拿到的一直是poweredOff或unknown导致功能一直异常却排查不到原因。分屏与多任务适配在两分的多选里出现了一次考的是iPad多任务环境下布局适配与生命周期变化。这个考点对做过iPad适配的人几乎是送分题但纯粹做iPhone开发的候选人很容易漏选。关键在于理解viewWillTransition和traitCollection变化以及在分屏宽度下SafeArea和布局约束的重新计算。推送相关没有直接出题但设计题里涉及到了应用内消息推送的触达策略我后面会细说。这里想提醒一点很多项目集成了第三方推送却在App启动时反复注册deviceToken既耗电又容易触发推送频率限制。正确的做法是token稳定之后判断没有变化就不重复上报这和笔试中unipush相关配置问题的排查思路是一致的——先确认厂商通道配置是否正确再检查token上报时机。3. 编程题与设计题实操复盘3.1 算法题LRU缓存机制编程题第一道是经典的LRU缓存要求实现get和put操作时间复杂度O(1)语言不限可以用Swift或Objective-C。这道题说难不难说简单也不简单能在一票候选人里筛出代码习惯。O(1)的get和put意味着必须用哈希表加双向链表Swift里可以用Dictionary配合自定义双向链表节点实现。不少同学写了数组版本代码很短很工整但时间复杂度不符合要求只能拿一半分。我建议的标准实现思路是哈希表的key映射到双向链表的节点节点里存key和value。get时如果key存在把对应节点移到链表头部然后返回value。put时如果key已存在更新value并移到头部如果不存在创建一个新节点放到头部再判断链表长度是否超过容量超过就删除尾部节点并同步删除哈希表里的key。这样每个操作都是O(1)。这里有一个容易忽略的细节删除尾部节点之后必须同时把哈希表里的key一并移除而双向链表的节点里必须存key否则你只知道value不知道要删除哈希表里哪个key。这个细节在笔试现场非常容易漏一旦漏了缓存容量就会越维护越脏。final class LRUCache { private class Node { var key: Int var value: Int var prev: Node? var next: Node? init(_ key: Int, _ value: Int) { self.key key self.value value } } private let capacity: Int private var dict [Int: Node]() private let head Node(0, 0) private let tail Node(0, 0) init(_ capacity: Int) { self.capacity capacity head.next tail tail.prev head } private func remove(_ node: Node) { node.prev?.next node.next node.next?.prev node.prev } private func addToHead(_ node: Node) { node.next head.next node.prev head head.next?.prev node head.next node } func get(_ key: Int) - Int { guard let node dict[key] else { return -1 } remove(node) addToHead(node) return node.value } func put(_ key: Int, _ value: Int) { if let node dict[key] { node.value value remove(node) addToHead(node) return } let newNode Node(key, value) dict[key] newNode addToHead(newNode) if dict.count capacity { let tailNode tail.prev remove(tailNode!) dict[tailNode!.key] nil } } }这段代码我建议直接背熟不仅因为LRU是高频考题而且它本身就是图片缓存、网络缓存里最常用的淘汰策略。面试官接下来大概率会追问一个问题为什么不用系统自带的NSCache这时候如果你的项目里用过NSCache就会知道NSCache是线程安全的而且会自动淘汰内存紧张时的对象但它不提供LRU顺序控制也不保证淘汰策略精确符合预期。LRU手写实现的好处是策略可控、顺序精确代价是锁和链表的维护成本需要自己处理。3.2 iOS实操题UIStackView实现自适应标签列表编程题第二道要求用UIStackView或AutoLayout实现一个标签列表标签数量不固定每个标签文字长度不固定要求标签按从左到右排列、自动换行整体垂直居中。这道题不只是考约束怎么写更考你对动态布局的理解。用UIStackView直接做自动换行是做不到的因为UIStackView的布局规则是线性排列要么全部横排要么全部竖排它不支持流式换行。正确的思路是使用UICollectionView或者手动计算每个标签的宽度逐行摆放。笔试现场时间有限我建议用UICollectionView的FlowLayout把estimatedItemSize设为UICollectionViewFlowLayoutAutomaticSize让Cell自适应内容宽度然后用自定义SectionInset和minimumInteritemSpacing控制间距。这样一个简单的标签列表就出来了而且天然支持任意数量的标签。不过这里有个坑estimatedItemSize自动计算在iOS 14以上表现良好低版本偶尔会出现约束不明确导致的布局警告所以在写答案时最好注明Base SDK版本和最低支持版本。如果题目明确要求必须用UIStackView实现那只能退而求其次用多个UIStackView按行嵌套每行根据已有宽度判断是否换行但这样计算复杂且性能不高。这道题实际上在考察候选人有没有“选对工具”的判断力而不是“只会一种写法”。3.3 系统设计题IM消息列表的架构设计最后一题是开放设计题设计一个IM类App的会话消息列表要求考虑消息收发、本地存储、未读计数、分页加载、多端同步说明技术选型理由。这道题没有标准答案但可以通过回答看出候选人有没有真实架设过复杂页面。我推荐的回答框架是分层设计。UI层用UITableView或UICollectionView数据源用DiffableDataSource减少reload整个列表的次业务层建立MessageCenter单例负责收发消息、更新未读、广播数据变化存储层用SQLite或CoreData按会话维度分表避免一次性加载全部消息网络层通过WebSocket保持长连接配合HTTP接口做消息补拉和失败重传。值得展开的是本地存储缓存策略。IM列表的特点是实时性要求高、数据量大、频繁读写直接操作数据库很容易造成主线程卡顿。我的做法是内存中维护一个会话列表收到新消息先更新内存然后通过异步队列把数据写入数据库UI通过回调刷新。这里要处理的一个细节是消息去重服务端下发的消息和本地补拉的消息可能重复所以本地数据库需要以消息ID建立唯一索引写入时做INSERT OR REPLACE。未读计数在多端同步场景下是个很容易出错的地方。如果用户在A端读了一条消息B端通过推送知道了新消息但未读计数没有同步就会产生红点混乱。合理的方案是本地维护未读数同时服务端在消息回执中附带全局未读数客户端以服务端为准做本地校准。这个思路虽然简单但在笔试回答里说出来明显要比“用Notification通知刷新未读数”这种方案高出一个层次。还有一个小点容易被忽略消息列表的图片和表情缩略图加载。如果每个Cell都实时从网络拉图列表滚动必然卡顿。要把缩略图统一走图片缓存框架列表滑动时只读缓存不触发网络请求这也是我在项目里用SDWebImage或自研图片缓存的原因。笔试中如果能把“列表流畅度”和“图片加载策略”主动联系上会是非常加分的细节。4. 常见失分点与避坑实录4.1 审题不清导致的典型翻车每次笔试改卷最遗憾的不是不会做而是会做却没看清题。这批试卷里有一道多选问的是“以下哪些写法可以避免循环引用”选项里有“在block开头用__weak typeof(self) weakSelf self”和“在block内部用__strong typeof(weakSelf) strongSelf weakSelf”。不少同学把两个都选上了但题问的是“避免循环引用”第二个选项并不是避免循环引用而是为了避免block执行过程中对象被提前释放。这两个知识点经常被混在一起笔试里把它们放到同一题的选项里就是专门用来区分“背过概念”和“真正理解”的。还有一种翻车是设计题没看场景限制。题目明确说了App同时支持iOS 11.0及以上版本这就在暗示你基于iOS 13才有的功能不能作为默认方案比如新的SceneDelegate生命周期管理、UICollectionView的Cell注册新API。如果答案里直接用了iOS 14的新特性而不兼容说明阅卷人会有理由怀疑你的上线经验不足。这类问题怎么避免我的经验是拿到试卷先别急着做选择把每个题干里“正确/不正确”“能/不能”“支持的最低版本”这类限定词圈出来单选的选项看完再下笔多选只选有十足把握的选项因为多选少选通常得一半分错选直接零分。4.2 代码题细节不严谨的表现编程题LRU那题代码逻辑写对的人不少但细节处问题很多。有人在get操作里忘了把节点移到头部有人在容量溢出时遍历数组找最久未使用的key还有人在删除双向链表节点时没有同步删除哈希表。这些细节现场写的时候都觉得自己是对的实际上跑测试用例才发现问题。我建议在笔试前专门花两天时间把LRU、LFU、反转链表、合并有序链表这四类高频题手写三遍以上写到不用想就能默写出来的程度考场上的时间压力会小很多。UIStackView那题还有一个细节很多人写答案时用的是纯代码创建约束但忘记设置translatesAutoresizingMaskIntoConstraints false这是一个非常低级的错误一旦忘记约束系统会警告布局错乱。我改简历里的代码时经常看到有人犯这个错笔试现场也出现了不止一次。这属于肌肉记忆问题平时写代码时多留个心眼形成习惯考场上就不会漏。4.3 系统框架与混合开发经验欠缺我在前面提到这套试卷考了CoreBluetooth系统级状态和App授权状态的区分。很多人根本不知道还有CBManagerAuthorization这个枚举考场上只能凭直觉回答。这个知识点在官方文档里写得很清楚但因为大多数项目只是简单调了下蓝牙API没有深入权限管理的边界情况所以被问倒很正常。我的建议是准备笔试前把系统框架涉及的权限模型全部过一遍相机权限、麦克风权限、定位权限、蓝牙权限、通知权限对照官方文档把“系统开关”“App授权”“用户拒绝”这几个状态分别列出来理解它们之间的组合关系。另外题目里涉及H5与原生通信的边界说明招聘方关注混合开发经验。这个领域有几个高频坑比如原生埋点回调时机不对、H5页面在iOS上滚动掉帧、WKWebView的Cookie同步问题。还有一个我实际遇到过的问题是小程序iOS端返回上一页时拿不到extraData这是navigateBack回调的数据在跨端传递时丢失的经典问题解决办法是在目标页面的onLoad里通过事件通道提前传递而不是依赖返回值。笔试不一定会直接考这类细节但如果简答题聊到混合开发方案能够把这些实战经验说出来会很加分。5. 备试路线与实用工具建议5.1 从基础到源码的三阶段计划如果距离笔试还有两到三个月我建议把备试分成三个阶段。第一个阶段大概三周目标是把语言基础和系统框架过一遍可以按单元刷题每天不用多三十到五十题就够了重点是理解每道题背后的原理而不是背答案。这个阶段一定要把官方文档当作主要的参考资料很多网上的博客讲的版本已经过时尤其是iOS 13之后权限模型、SceneDelegate、后台任务这些新版API以官方文档为准。第二个阶段大概四周进入源码阅读和实战复现。Object-C的Runtime源码开源的Runloop的源码网上也有整理好的版本我建议至少把objc_msgSend的查找流程和Runloop的source/timer/observer机制读一遍源码。不是让你背源码而是要能画出流程图用自己的话讲清楚每一步在干什么。这个阶段还可以搭配做几个小项目比如自己写一个图片缓存框架、搭一个IM消息列表把笔试里的设计题落地成真实代码这个过程的收获比刷一百道题都大。第三个阶段是考前三到五天的冲刺重新过一遍高频考点清单把每个知识点用“一句话结论加一个场景例子”的方式整理出来方便快速复述。考前一天不要再看新题早点休息保证笔试当天的状态。我个人体会是笔试的时间紧张程度高于面试真正拉开差距的往往不是知识面广度而是熟练度平时写代码速度快、习惯好的人笔试成绩通常不会差。5.2 工程调试工具Charles、模拟器与自动化很多同学准备笔试只知道刷题忽略了一个隐性考察点工程调试能力。虽然笔试不会让你现场配置环境但简答题里如果提到线上问题排查熟悉调试工具的人回答起来会明显更有底气。Charles是iOS开发排查网络问题最常用的工具能抓HTTPS包的关键在于给模拟器或真机安装并信任Charles的SSL证书。如果你的基础配置正确但仍旧抓不到包优先检查两点一是代理是不是只设置了HTTP没设置HTTPS二是目标App是否开启了SSL Pinning如果开了证书校验基础抓包手段就会失败。这背后考察的无非是HTTPS握手机制理解。iOS模拟器在笔试准备中也很有用很多人不知道模拟器支持多个设备的模拟运行可以快速验证不同尺寸下的布局和分屏状态。我在准备分屏适配考点时就是直接在模拟器里选择不同的iPad分屏模式看布局是否异常比在真机上反复横拖高效得多。自动化测试也是简历和面试中的加分项。XCTest和XCUITest是苹果官方方案如果你能在项目里写上几条UI自动化用例说明你具备基础的质量保障意识。笔试如果问“如何保证IM消息列表的稳定性”把自动化回归测试作为方案之一提出来会比只谈功能开发全面得多。5.3 证书、签名与上架准备还有一类知识虽然笔试没直接出题但春招入职之后马上会用到就是iOS开发者证书和上架流程。很多新人对证书配置一头雾水导致打测试包都费劲。开发者App证书更新是一个非常典型的坑证书过期后所有使用该证书签名的安装包都会出现无法安装的问题而解决方式不是重新生成证书那么简单还需要同步更新描述文件Provisioning Profile并在打包机上重新下载安装证书和描述文件。如果是用uni-app这类跨端方案打包iOS测试包需要先配置好Bundle Identifier、证书和描述文件然后在HBuilderX或命令行工具中执行打包。整个流程中最容易出问题的环节是描述文件里的设备UDID没有包含测试真机导致安装失败。新人在入职前自己完整走一遍“创建证书、注册设备、生成描述文件、打包、真机安装”的流程会非常有帮助面试聊到项目上线流程时也能有话说。关于上架审核我还想多说一点。很多人以为App上架只是点个提交按钮实际上审核被拒最常见的原因集中在隐私权限描述、用户协议缺失、使用私有API这三大类。其中隐私权限描述需要提供准确的使用场景说明审核人员会逐条核对这也是为什么我在前面强调要理解权限模型而不只是会写Info.plist里的字符串。写在最后的一点体会这批试卷整体出得比较务实没有偏题怪题所有考点都能在平时工程实践中找到对应场景。我个人改完这批笔试卷最大的感受是iOS岗位的招聘门槛已经不像前几年那样只看语言基础了系统框架的理解深度、混合开发的工程经验、线上问题的排查能力正在成为区分候选人的关键维度。如果你正在准备下一批笔试建议把重心从刷题转移到“理解原理、动手实践、总结复盘”这三件事上毕竟笔试考的不只是你会不会这道题而是你在真实项目中能不能像写这套卷子一样把问题考虑周全。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门