
1. 笔试整体设计与考核思路拆解1.1 试卷结构与考点分布欢聚时代2018校招的IOS B卷放在当年的大环境里看算是很有代表性的一套题。那几年移动端招聘正处在“会写UI就能进”向“必须懂原理才能过”的转型期很多公司还在问“怎么用AFNetworking发请求”这种级别的问题而欢聚这套卷子已经有了明显的筛选意识它不考你背了多少API而是考你在真实开发里踩过多少坑、能不能把“为什么这么写”讲清楚。整套卷子我个人把它分成四块基础语言题、原理机制题、架构设计题、场景实战题。基础语言题主要落在Objective-C的语言特性上比如属性关键字、内存管理、消息发送机制原理机制题集中在Runtime、RunLoop、多线程、Block这块架构设计题会给你一个业务场景问你怎么拆分模块、怎么选型场景实战题则贴近直播、IM这类欢聚当时的核心业务涉及弱网处理、流量优化、界面流畅度保障等。整体来看这套题并没有故意出偏题怪题但覆盖面很广如果你只是刷过面试题库而没有真正写过完整项目很多题会答不到点子上。1.2 出题背后的选拔逻辑我后来自己也参与过校招出题回过头看这套卷子能明显感觉到出题人的三层意图。第一层是筛“有没有真写过程序”。比如内存管理相关的题目如果你只是背过“ARC下不用管内存”这种结论遇到循环引用的场景题基本就露馅了。第二层是筛“有没有主动思考过原理”。UIButton的点击事件是怎么传递到target-action的这个问题的背后是RunLoop、事件响应链、消息转发一整条链路能答出层次的人说明平时看代码不只是看调用而是会往底层钻。第三层是筛“能不能在团队里干活”。卷子里那些开放性的设计题没有标准答案但你的回答里能不能体现出模块划分意识、容错处理意识、可测试性意识阅卷人一眼就能看出来。说白了这套卷子不是在考知识点本身而是在考“你脑子里的iOS知识体系是零散的还是成网的”。这一点不管你是准备校招还是已经工作几年回头补基础都是最值得琢磨的地方。2. 高频考点详解与实操要点2.1 OC语言与内存管理核心题先聊聊这套卷子里最基础也最容易丢分的部分OC语言特性和内存管理。很多同学觉得这部分简单不就是strong、weak、copy这几个关键字嘛但出题人稍微换个问法就能难倒一大片。比如有一类经典题定义一个NSString属性什么时候用copy什么时候用strong如果只答“NSString用copyNSMutableString用strong”这种口诀分数不会高。要答得漂亮得说清楚copy修饰的属性在setter方法里会执行一次copy操作当外界传入NSMutableString时赋值给属性的是它的一份不可变拷贝这样外部后续修改原可变字符串不会影响属性值而strong只是retain外部改了什么属性就跟着变。再往深一层你还可以提一下copy的两种方式——不可变拷贝和可变拷贝分别对应copy和mutableCopy以及为什么NSArray、NSDictionary这些容器类型建议用copy修饰来防止外部可变容器被意外修改。另一类常考的是循环引用。出题人通常会给你一段代码比如一个Block里使用了self问会不会导致内存泄漏。只答“会要用weakSelf”是及格线想拿高分得把完整的处理逻辑讲清楚先用__weak修饰self生成弱引用在Block内部如果还需要强引用保证self在Block执行期间不被释放就要再用__strong修饰临时持有一下也就是我们常说的weak-strong dance。还要说明为什么要这样处理——因为Block会捕获外部变量并对其产生强引用如果Block被self持有就会形成self - block - self的引用环导致双方都无法释放。更进一步GCD的Block是否会产生循环引用、UIView动画Block是否需要注意这些对比性的思考非常加分。这里要特别提醒一点很多同学答内存管理只盯着引用计数忽略了内存泄漏还有另一个大头NSTimer。NSTimer会强持有target如果你在ViewController里创建了一个timer并repeat却没有在dealloc里invalidate那这个控制器永远不会被释放。这也是当年这套卷子的高频坑点我印象很深。2.2 Runtime与消息机制原理题Runtime这块是欢聚这类大厂校招的必考模块。原因很简单它属于“面试造火箭、工作拧螺丝”里的火箭部分看起来日常工作用不上但它决定了你对OC的理解深度。这套卷子里的Runtime题目我印象比较深的有这么几类。一是消息发送机制问你[obj doSomething]这行代码在底层经历了什么。标准回答链路是编译器把方法调用转换为objc_msgSend函数调用这个函数会先去obj的isa指针指向的类对象里查找方法缓存缓存没命中就去方法列表里找找到就调用并加入缓存找不到就沿着superclass指针逐级往上找一直到NSObject还没有就进入动态方法解析环节——这里有三个救命稻草resolveInstanceMethod、forwardingTargetForSelector、methodSignatureForSelector和forwardInvocation。能把这套流程讲完整面试官基本就会点头了。二是方法交换。当年很多第三方库和黑科技都靠Method Swizzling实现出题人会问你怎么在不修改源码的情况下给一个类的方法加日志。这道题的考点不只是API调用更重要的是风险意识。你得主动提到方法交换要在load或initialize里做并且要加dispatch_once保证只执行一次交换时要用class_addMethod判断目标方法是否真的存在避免交换到父类的方法交换之后如果还需要调用原实现要保存好原来的IMP。这些细节说明你踩过坑而不是只在博客上看过demo。三是关联对象。问你是否能在Category里添加属性。答案是能声明property但不会自动生成ivar和setter/getter需要用objc_setAssociatedObject和objc_getAssociatedObject手动实现。这里有个容易被追问的点关联对象什么时候释放正确理解是关联对象会在宿主对象dealloc时被释放但释放顺序并不保证所以如果关联对象内部还持有其他资源要格外注意。如果要答得更有深度可以提一下关联对象本身的存储结构——全局的AssociationsHashMap按对象地址关联到ObjectAssociationMap再映射到关联值和策略这也是为什么不同对象同名的关联key不会冲突的原因。2.3 Block与多线程并发题Block是OC里绕不开的核心也是笔试区分度很大的一块。原因在于很多人会用Block但说不清楚Block的底层结构。这套卷子如果考Block大概率会从这几点切入Block本质是一个结构体内部包含isa指针、函数指针和捕获的变量三种Block类型——_NSConcreteGlobalBlock、_NSConcreteStackBlock、_NSConcreteMallocBlock分别对应什么场景捕获外部变量的规则——局部变量是值捕获__block修饰的变量是引用捕获静态变量和全局变量直接通过指针访问。这里有一个高频追问为什么Block里修改局部变量要加__block因为Block捕获外部局部变量时默认是把它作为const值拷贝进结构体你在Block里改的是拷贝后的那份值根本改不到原变量。加了__block之后编译器会把这个变量包装成一个结构体Block捕获的是这个结构体的指针所以能修改到原值。如果能把这一步展开讲清楚顺便提一下__block变量在Block被拷贝到堆上时也会跟着迁移就非常加分了。多线程这部分当年考得最多的是GCD和NSOperation的区别。你至少得说出来GCD是纯C接口轻量级NSOperationQueue是OC对象、支持取消、依赖关系和KVO监听然后往下深入为什么iOS开发中更推荐使用NSOperationQueue做复杂任务编排因为可以随时 cancel可以在任务之间加依赖可以设置最大并发数控制资源消耗。同时你也要会手写一个串行队列同步执行和异步执行的输出顺序题这类题在笔试题里几乎年年出现。比如dispatch_async到串行队列嵌套dispatch_sync到同一个串行队列会发生什么——答案是死锁因为同步任务在等待当前队列执行完而当前队列又在等待这个同步任务执行两个互相等待。这个坑我当年就跳过后来做了很多次实验才算彻底理解。3. 架构设计与项目实战相关题目3.1 iOS架构模式对比与选型这套卷子后面的开放题大概率会涉及架构设计。给你一个具体业务场景比如直播聊天室、短视频信息流或者IM会话列表让你设计技术方案。这类题的考查重点不是你是否用过某个框架而是你有没有形成自己的架构思维。首先要能清晰地对比MVC、MVP、MVVM这几种架构的优缺点。MVC在iOS里的标准形态是ViewController既是View又是ControllerModel层独立问题是Controller越来越臃肿也就是业内常说的“ Massive View Controller”。MVP把ViewController里的业务逻辑抽到PresenterView和Model完全隔离但需要维护大量的协议回调代码量会明显增加。MVVM用ViewModel替代Presenter配合RAC或者Block实现数据绑定能大幅瘦身Controller但调试时数据流向不如MVC直观学习成本也不低。在笔试里怎么答这类题呢我的建议是不要站队说哪个最好而是体现“选型是权衡”的思路。比如项目刚起步、团队不大、业务以页面展示为主MVC完全够用没必要为了架构而架构如果业务逐步复杂Controller膨胀明显可以渐进地把业务抽到ViewModel配合单向数据流实时的强交互场景比如直播间里的礼物动效和消息弹幕要更关注视图更新频率和内存峰值单纯套MVVM反而会引入额外的复杂度和性能开销。这种回答方式给阅卷人的感觉是这个候选人真的写过项目有自己的判断力。3.2 混合开发方案选型细节2018年那会儿正好是Hybrid方案百花齐放的阶段欢聚这类做直播社交的公司混合开发已经是绕不开的议题了。卷子里如果出现“如何选择合适的混合开发方案”这类题你就要把几个主流方案的适用边界讲清楚。UIWebView和WKWebView的对比是基础中的基础。至少要答到WKWebView运行在独立进程崩溃不影响App主进程WKWebView自动管理JS和OC的桥接性能更好内存占用更低但WKWebView也有自己的问题比如Post请求会丢失body、Cookie同步策略和UIWebView不一致、加载本地文件有额外的安全限制。这些细节如果不实际操作过很难答全却是真正的加分项。再往后是React Native、Flutter这类跨端框架的对比。这套卷子当年应该还没有Flutter但今天再回头看选型思路是通用的React Native的优势是热更新能力强、生态完善、JS语言上手快劣势是性能瓶颈在列表和动画这类高频场景桥接通信存在额外开销Flutter的优势是渲染引擎自绘、UI一致性好、性能接近原生劣势是Dart语言相对小众、包体积偏大、动态化能力弱。你要记住的一个核心原则是混合开发方案没有银弹关键是看你的业务场景更侧重什么。如果只是简单的网页展示那就开个WKWebView加载H5就行千万不要为了技术炫技引入一整套跨端框架。3.3 界面布局、UIStackView与分屏适配布局这块也是笔试常客。2018年那会儿Auto Layout已经是大势所趋但XIB和纯代码派还有很大争议。这套卷子如果问界面布局核心考点应该是你用什么方式写UI为什么选它有没有遇到什么坑。关于UIStackView我觉得需要重点说说。UIStackView在iOS 9才开始支持但到2018年其实已经算成熟方案了。它解决的核心痛点是手动管理多个控件的约束太麻烦尤其是等间距排列、均匀分布这类布局用StackView只需要设置axis、spacing、distribution几个属性就能搞定而且动态增删子视图非常方便配合hidden属性还能自动调整布局做自适应高度特别顺手。这些特性后面几年大家在开发中都用得非常多实属iOS布局里必会的一项技能。分屏适配也是可以延伸的考点。iOS 9加入了Slide Over和Split View有些公司会专门问你在iPad上App怎么适配分屏。核心知识点是要正确设置size classes让不同尺寸下能呈现不同布局要避免硬编码宽度多用相对布局和优先级约束要关注键盘弹起时视图怎么避让因为分屏下键盘形态变化更频繁还有内存警告的处理分屏下App可用内存会更紧张不处理好很容易被系统杀掉。这套逻辑到今天依然适用苹果设备形态越来越多自适应布局能力已经成为基本功。3.4 自动化测试与调试经验从热搜词里能看到很多人关注“ios自动化”和调试工具这其实是校招中容易被忽视但很加分的板块。虽然笔试不一定直接考面试追问时如果提到你有自动化测试意识会明显提高评价。iOS自动化的主流方案有两类一类是UI层测试用XCTest的XCUIApplication做端到端自动化或者用Appium这种跨平台方案一类是单元测试用XCTest对核心业务逻辑做验证。笔试如果问“如何保证代码质量”别只答“测试”要展开讲核心算法和数据处理层做单元测试关键路径做UI自动化回归接口层用Mock数据模拟不同返回再加上CI流水线里配置自动化构建和测试触发。这套组合拳下来说明你有工程化思维而不只是会写页面。调试这块Charles抓包也是必备技能。要会配SSL Proxy解密HTTPS要会Map Local做接口Mock要会Breakpoint修改接口返回值还要会模拟弱网。很多时候线上问题找不到原因就是用Charles把接口改成极端返回结果复现的。最新版系统上抓包工具的限制越来越多回归测试环境时记得把证书相关的调试配置处理好不然包抓不下来还以为是App有问题。调试类问题在面试里常常被用来判断候选人的排查思路是否清晰强烈建议提前练熟。4. 常见问题与排查技巧实录4.1 校招笔试常见丢分点我把这些年看到的校招笔试暴露出的问题整理成了一张表基本每年都能在卷面上看到同样的错误丢分点典型错误表现正确思路属性关键字“想当然”copy和strong随便写不知道String用copy是为了防可变类型篡改按“谁持有谁负责”原则分析存储语义说到setter实现层面循环引用只看表象只知道Block要weakSelf不知道什么时候不需要区分Block是否被self持有说了weakSelf后面记得说strongSelf的必要性Runtime知识点散装能背出几个函数名讲不清消息查找链路和兜底流程按“缓存查找-方法列表-父类链-动态解析-转发”顺序完整体述多线程题凭感觉dispatch_sync和dispatch_async混用场景没想清楚答错执行顺序或死锁现象画清队列与任务的关系串行/并行与同步/异步两轴分开判断架构题答成名词解释只会说MVVM比MVC好分析不了自己的项目结合一个具体页面讲清楚各个角色分别是谁、数据怎么流动、有什么取舍我特别想强调表格里第二行那条。很多人在复习时背了“Block里用weakSelf”结果一碰到“某个Block其实并没有被self持有”的题就慌。判断一个Block是否会造成循环引用唯一的标准是“是否存在一个引用闭环”而不是见到Block就无脑weak。比如UIView的animateWithDuration动画Block它是由系统持有并执行的并不被self持有所以你在动画Block里直接用self也不会造成循环引用。但为了保险起见很多代码规范还是建议统一用weak主要是为了防止Block被延迟执行时self已经被释放会多占用一段时间内存并非循环引用问题。这个细微区别笔试时能区分开含金量立马上来了。4.2 经典错题复盘一个Block捕获变量的案例我挑一道当年评论区讨论很热烈的题目复盘一下。题目大概是这样的有一段代码在外面定义了一个局部变量index然后在一个循环里给三个Button都添加了相同的点击事件事件Block里打印index问你运行后点击三个Button分别输出什么。很多人不看细节直接答0、1、2正确答案是——如果你在循环体内定义了局部变量button并用Block捕获每次都把index作为值拷贝进来那三个按钮输出的确实分别是0、1、2但如果你只定义了一个button并在循环外复用它或者你的Block捕获的是同一个变量那点击三个按钮输出就都是2。这个案例的考点就是Block对局部变量的值捕获机制以及在循环中创建视图时的典型坑。这个问题的实战价值非常高。我在实际开发里就遇到过类似问题给列表里的每个Cell上的按钮加点击事件结果发现点击任何一个按钮回调里拿到的都是最后一个Cell的下标。原因就是我在循环外复用了同一个index变量Block捕获的是变量的值而循环结束后这个值已经变成了最大值。大家以后遇到类似问题排查思路应该是先看捕获的变量是值类型还是对象类型再看Block是被谁持有、什么时候执行的最后确认变量是否在Block执行前被修改过。如果发现自己就是在循环里用Block捕获循环变量直接加一个中间变量或者用Swift的capture list就能解决。4.3 面试现场追问应对技巧笔试过了之后面试官往往会拿着你的笔试卷子追问。这一环节翻车的人不在少数基本都是因为笔试时蒙对了一道题但追问时经不起深挖。有一个技巧我一直觉得很有用面试官追问题目的时候不要急着抢答先用几秒钟在脑子里把这道题涉及的知识链路画出来从结论往前推把涉及的前提条件快速过一遍。假如他问“在什么场景下MVC会不够用”你先不要顺着说MVVM多好而是先说清楚MVC在这个场景里哪里撑不住了——Controller膨胀、状态多导致难以跟踪、模块复用性差——然后再说你尝试过什么改进方案、效果怎么样、还有什么遗留问题。这种由浅入深的回答节奏比自己激动地倒豆子一样背文章要好得多。还有一个应对策略是“主动抛出边界条件”。面试官问“你平时怎么做网络层封装”的时候你可以先反问一句“你指的是单机版还是业务集成场景下的封装”这会显得你考虑问题有范围感。然后你可以顺着网络层讲到DNS解析、HTTPDNS、连接复用、请求优先级、缓存策略、错误码统一处理、流量统计、安全校验这些点你只要每个能展开说两三句面试官就会觉得你的知识面是立体的。顺便说一下这套话术在校招季我几乎每次模拟面试都推荐反馈一直很好。5. 从笔试到Offer的复习路径建议5.1 三轮复习法说了这么多知识点和题型最后聊聊怎么高效准备。如果你是准备校招的同学我建议你用三轮复习法每一轮的侧重点完全不同。第一轮是“扫盲搭骨架”。目标是把iOS知识体系里最核心的主干过一遍包括OC语言特性、内存管理、Runtime、RunLoop、多线程、网络、存储、UI布局、架构模式。这一轮不需要刷题而是看书、看文档、看高质量博客建立知识地图。我当年用的是“官方文档为主、国内高质量博客为辅”的组合遇到不懂的概念先去Apple Developer文档瞄一眼原始定义再去看别人的解释这样理解会比较准。第二轮是“以题带点”。拿着历年校招真题和主流面试题集按专题一块一块刷。每道题不能只看“这题怎么答”要逼自己说清楚“这道题背后考的是什么知识点”而且一定要动手写代码验证。比如RunLoop的Source0和Source1区别光背没用要在Xcode里用断点观察RunLoop的mode切换用Instrument的RunLoop工具看卡顿发生在哪个阶段。只有动手验证过笔试时你才能快速反应过来出题人在考什么。第三轮是“模拟实战输出”。这一轮最重要的就是强行把自己学到的知识讲给别人听。你可以找同学组队互相面试也可以自己对着录音讲一遍某个专题然后回放听哪里卡壳了。卡壳的地方就是你的知识盲区补到不卡为止。输出是最好的学习方式这一点我屡试不爽。等你把整条知识链都能不看资料顺畅讲出来的时候笔试基本就已经稳了。5.2 代码能力与项目经验怎么补笔试和面试里还有一个很现实的问题很多同学的简历上写着熟悉iOS开发但实际项目经验几乎为零。这道题怎么破我的建议是大二大三就开始做个人项目不用大但一定要完整。完整的意思是有网络层、有数据持久化、有复杂的界面交互、有上架或被真机测试的经历。哪怕只是一个仿写的小应用只要你把每一个模块的选型思路都理清面试时就有源源不断的素材可讲。具体的项目选题我比较推荐做三类第一类是工具类App比如记账、习惯打卡重点练数据持久化和复杂状态管理第二类是信息流类App重点练列表性能优化和图片加载缓存链路第三类是IM或聊天室类App重点练即时通信、消息重发机制、弱网处理。这三类项目基本覆盖了移动开发的大部分核心考点做完一个就能顶好多空话。如果你已经有了项目但觉得自己讲不出亮点可以试试这个办法把项目里最复杂的一个页面单独拎出来按“需求背景-技术方案-踩坑记录-后续优化”四个维度各写几百字。面试官让你介绍项目时你就有故事可讲而不是干巴巴地说“我做了一个仿微博的App”。5.3 准备过程中的心态与时间投入最后想聊聊心态问题。校招准备是一场持久战很多人前期冲劲很足刷了两周题觉得“怎么还有这么多不会的”就焦虑了。我自己的感受是焦虑的根源是“感知不到自己的进步”。破解方法很简单做一个知识清单把iOS核心知识点列出来每搞定一个就打一个勾每周回顾一次看到勾在变多心态自然就稳了。时间投入上如果每天能保证4到6小时的高效学习一到两个月的准备周期是够用的。前期按专题推进后期以真题和模拟面试为主。越到后面越要减少刷短视频和碎片阅读的时间把整块时间留给深度学习和代码验证。相信我那些拿到Offer的人不是比谁聪明多少而是比谁更能在别人放弃的时候多坚持了一轮。写在最后的一点个人体会这套欢聚时代2018校招IOS B卷放到今天来看虽然题型有些年头了但它的出题逻辑一点都不过时。它不考偏题怪题每个知识点都是日常开发里用得上的而且极其强调“知其然更知其所以然”。我自己在校招季过后复盘时最大的感悟是靠记忆准备面试是走不远的只有靠理解构建起的知识体系才能在笔试和面试里游刃有余。如果你正在准备iOS校招或者工作两三年后想回头补基础我的建议是不要只刷题要动手验证每一个结论。Block捕获机制你写个demo跑一下RunLoop的mode切换你用断点观察一下循环引用你用Instruments的Leaks工具测一下这些实打实的操作比背十篇面经都有用。希望这篇拆解对你有所帮助祝你在即将到来的校招季里也能拿到心仪的Offer。—— 顺手考考你UIButton的点击事件从触发到调用target-action中间经过了哪几层传递这条链路里每一层都有机会被拦截你能不能说出至少两个可以拦截的位置想清楚这个答案你对iOS事件处理的理解就比大多数校招候选人强了。