2023秋招小红书iOS笔试:考点分布、编程题思路与备考路线
2026/9/5 4:17:00 网站建设 项目流程

2023年秋招那会儿,我投了小红书的iOS开发岗,第一关就是笔试。小红书这批笔试是线上牛客网做的,全程开着摄像头,限时90分钟,题量比我预期大不少,客观题加编程题加起来接近四十道。考完之后我最大的感受是:它不只是考你会不会写代码,更是在筛你有没有完整的iOS知识体系,以及对常见坑有没有实际踩过的认知。这篇文章就围绕2023年秋招小红书iOS开发岗第一批笔试,把题型分布、知识点拆解、编程题思路和备考路线一次性讲清楚,给后面准备校招iOS岗的同学做个参考。

1. 笔试整体情况与考点分布

1.1 笔试平台与流程安排

先说流程。小红书秋招的笔试统一走牛客网,收到邮件之后可以选时间段进入考试。第一批发卷时间一般在9月上旬,每个批次题目不完全一样,但考察范围和难度基本是一个量级。进入考试之后,系统会要求打开摄像头、开启屏幕录制权限,中途切出页面会有提醒,切出次数多了会被标记异常,所以考试前最好把手机通知全关掉,浏览器只留一个标签页,避免误触。

整个笔试时长90分钟,题型分单选、多选和编程题。客观题大概占一半以上,编程题一般是两道到三道。客观题覆盖的范围很广,不只是iOS,还包括数据结构、操作系统、计算机网络这些计算机基础。我印象里iOS岗的笔试会把客观题分成两大部分:一部分是通用计算机基础,另一部分是iOS专项。通用部分主要靠平时算法和计算机基础功底,iOS专项就是看你对OC/Swift语言、Runtime、RunLoop、内存管理、UI和系统框架这些内容掌握得够不够细。

编程题的输入输出格式是牛客标准模式,需要自己写输入解析。有些人LeetCode刷习惯了,每题给的都是核心函数,突然遇到这种要自己处理stdin的题目会有点慌,这个在备考阶段一定要提前适应。

1.2 客观题考点图谱

我根据自己的记忆和一起笔试的同学反馈,把客观题的考点整理成了下面这个表。当做一个“体检清单”用,每个点都能说出个所以然,笔试基本就稳了。

分类具体考点常见出题角度
OC/Swift语言属性关键字、block、KVO/KVC、Category、Swift可选型给一段代码问输出/是否编译通过
内存管理ARC、weak/strong、循环引用、autoreleasepool判断引用计数变化、找循环引用
系统框架RunLoop、GCD多线程、网络、UI生命周期、布局问你某种操作发生在哪个时机
计算机基础数组/链表/树、排序、哈希、复杂度选择题综合考察
操作系统进程线程、死锁、虚拟内存概念辨析类
网络TCP三次握手、HTTPS流程、HTTP状态码流程排序、协议机制
工程实践调试、性能优化、日志、崩溃分析给一个线上问题问排查思路

这里有一个容易被忽略的趋势:小红书这类内容社区App,非常看重候选人对“列表流畅度”和“图片加载”这两块的理解。所以笔试里关于UITableView滑动卡顿、图片缓存策略的题并不少见。你要是只背了八股没实际调过性能,碰到这种题就会觉得每个选项都对,实际上它们考察的粒度完全不同。

1.3 编程题的题型特点

小红书的笔试编程题难度属于中上游,不会出那种全场没人做出来的压轴怪题,但也别指望送分。我遇到的题型大概是:一道偏字符串/数组处理的题,一道偏数据结构(链表或二叉树)的题,再有一道可能是动态规划或贪心。

很多同学容易犯的错是把编程题当成LeetCode原题来背,实际上笔试出的题会有很强的“业务包装”。比如题干会写成“小红书有n篇笔记,每篇有发布时间和点赞数,需要按某种规则排序”之类的场景,去掉包装之后核心还是排序或区间合并。读题时先把业务词汇剥掉,抽成纯数据结构问题,思路会清晰很多。

2. iOS核心考点深度拆解

2.1 内存管理:从ARC到循环引用排查

iOS笔试对内存管理的考察非常细致,不是问“什么是ARC”这种概念题,而是给你一段代码,让你判断某个对象什么时候释放、引用计数是几、会不会造成循环引用。

先说ARC。ARC是编译器在编译期自动插入retain/release/autorelease的机制,它不是一个运行时垃圾回收器。这意味着编译器必须能静态分析出对象的持有关系,分析不出来就会产生错误或泄漏。属性关键字里,strong表示强持有,weak表示弱持有且对象释放后自动置nil,copy会拷贝一份新对象,assing对ObjC对象不安全,对基本类型没问题。

笔试里最常考的循环引用场景有三个。第一个是block:对象持有block,block又捕获了self,就会形成self -> block -> self的环。解决办法是用__weak __typeof(self) weakSelf = self; 在block里再用strongSelf判空。第二个是delegate:delegate属性要声明为weak而不是strong,否则两个对象互相强持有就泄漏了。第三个是NSTimer或CADisplayLink:target是self时,timer会被runloop持有,如果不invalidate就永远不释放。

我还记得有一道题是拿__weak和__unsafe_unretained做对比,很多人会忽略后者。__unsafe_unretained也是弱引用,但对象释放后它不会自动置nil,变成野指针,访问就会crash。笔试里问“下列哪个关键字在对象释放后会产生野指针”,答案就是它。

2.2 Runtime与消息机制:理解动态性的钥匙

Runtime是iOS笔试的重头戏。ObjC是一门动态语言,方法调用本质上是给对象发送消息,也就是objc_msgSend。消息发送的流程是:先查对象的isa指针找到类对象,再在类的method_list里找method,找不到就去父类找,直到根类,再找不到就走消息转发流程。

笔试常考的一个点是消息转发的三个阶段:动态方法解析(resolveInstanceMethod)、快速转发(forwardingTargetForSelector)、完整转发(methodSignatureForSelector + forwardInvocation)。你可以把这个流程理解成:一个员工找不到人处理任务,先问自己能不能现场学,再问有没有同事能帮忙,最后还要把一个完整任务包发给别人。问你“哪个方法可以为类动态添加方法实现”,答案就是resolveInstanceMethod,它内部调class_addMethod。

KVO的底层原理也是高频题。KVO通过isa-swizzling动态生成一个NSKVONotifying_XX子类,重写被观察属性的setter方法,在setter里调用willChangeValueForKey和didChangeValueForKey,从而通知观察者。所以一个对象被KVO之后,它的isa指针其实已经变了。考到“KVO为什么能生效”时,答出这个派生类和isa-swizzling就够一半了。

Method Swizzling也是常客。它利用Runtime在运行时交换两个方法的IMP。要注意的是,交换应该在+load方法里用dispatch_once包一层,避免重复交换;交换的是实例方法还是类方法要看获取Method时传的是class还是metaClass,这些细节笔试经常挖坑。另外现在主流做法是尽量避免Swizzling,用它要有完整的降级方案,毕竟它牵扯到全局所有实例,出了问题很难复盘。

2.3 RunLoop、多线程与并发

RunLoop是iOS开发者每天打交道又容易说不清的东西。RunLoop本质是一个事件循环,iOS的App启动后主线程就进入一个runloop,不停地接收触摸事件、定时器事件、网络事件,空闲时就睡眠,有事件就唤醒处理。笔试里常考RunLoop的Source/Timer/Observer三种输入源,以及它和AutoreleasePool之间的关系。

Source1是系统事件源,触摸事件就是通过Source1发到App的;Source0是自定义事件源,需要手动唤醒线程;Timer就是定时器。每次RunLoop循环结束时,会自动释放当前AutoreleasePool,这也是为什么主线程创建临时对象不会无限堆积内存。

GCD部分考得最频繁的是队列和死锁。串行队列、并发队列、主队列这些概念必考,dispatch_sync和dispatch_async的区别也是送分题。真正容易错的是死锁场景:在主队列上调用dispatch_sync(主队列)就会死锁,因为主队列是串行队列,你在执行当前block的同时又向同一个串行队列提交一个需要等待的空block,两个互相等待,永远执行不完。类似地,在一个串行queue里再dispatch_sync到它自己,也会死锁。

信号量dispatch_semaphore也值得复习,它用来控制并发数量或做同步等待。笔试喜欢问“semaphore初始值为N,M个任务并发,最多同时执行几个”。这个理解源码就清楚了,每次wait信号量减1,为0时阻塞,所以答案是N。还有dispatch_once,保证block只执行一次,内部也是用了信号量和原子操作。

2.4 UI、系统框架与性能优化

UI这部分的笔试题目通常在考察你是否真的理解布局和渲染,而不是只会在Xcode里拖控件。UIStackView、Auto Layout、frame/muBounds的区别、UIView和CALayer的关系,这些都要能说清楚。

比如UIStackView在iOS 11以后有了很多改动,stackView会根据axis、spacing、distribution自动管理子视图约束,但它并不会自动解决所有布局问题,子视图的intrinsic content size、压缩阻力和抗拉伸优先级都会影响最终效果。如果你不理解这些优先级,遇到stackView里文字被截断的问题就没法排查。

性能优化方面的考点更贴近小红书这类业务。列表卡顿的常见原因包括:cell的layout重复计算、图片解码在主线程、离屏渲染过多、混用的图层合成开销过大。提高列表流畅度的常规手段有:cell高度缓存、异步绘制、预排版、图片尺寸压缩、避免在cellForRow里做耗时操作。iOS 14开始UICollectionView的prefetching机制也是一个考点。

还有系统框架的细节题,比如CoreBluetooth的CBCentralManager的系统级蓝牙授权状态和App内蓝牙开关状态是两回事,系统弹出授权弹窗后需要回调处理。iOS 13以后新增了CBManagerStateUnauthorized等状态,App要在状态回调里统一处理。这类题表面上考蓝牙,实际是看你对系统API的状态机有没有完整认知。

电池优化也偶尔出现在校招笔试里。它主要涉及定位精度选择、后台任务、推送方式和屏幕刷新率。很多人不知道iOS的省电模式会限制CPU频率和网络请求行为,导致后台任务表现不一致。这类题目一般不会很尖刻,但你得能把优化方向和系统机制对应起来。

3. 编程题实战与解题策略

3.1 高频算法题型的解题框架

小红书笔试题的算法难度约等于LeetCode中等题。我把几个高频题型和对应框架整理了一下,这部分备考性价比最高。

字符串和数组处理是每次笔试几乎必出的。常见思路是双指针、滑动窗口、哈希计数、区间合并。比如“找出最长不含重复字符的子串长度”用滑动窗口,right指针不断右移,用哈希表记录字符最后出现位置,遇到重复时left跳到重复位置+1,过程中维护最大长度。笔试如果出这类题,写出维护左右指针的循环,再确认一下left取值逻辑,基本就能过。

链表题必背的是反转链表。迭代法用pre、cur、next三个指针滚动;递归法的核心是先翻后面,再让后面节点的next指向前一个节点。这两套代码顺手要能10分钟内写出来。二叉树常考层序遍历、前中后序遍历、最近公共祖先、路径和。层序遍历用队列做BFS,每层循环前先拿到当前队列size,就是这一层的节点数。这个模板在LeetCode 102里就是原题,笔试时候直接套。

动态规划和贪心对很多人来说是瓶颈。要是备考时间紧,优先把背包问题、最长递增子序列、最大子数组和这几个经典模型吃透。比如最大子数组和用Kadane算法,遍历时维护当前累加和cur和全局最大和max,cur小于0就重置为0,最后max就是答案。这类题一旦理解状态转移方程,反而比链表题好写。

3.2 笔试环境下的应试技巧

编程题在笔试环境里和在IDE里刷题完全是两种体验。首先是用例输入要自己处理。牛客的输入是一行或多行,你要用NSString读取整行再按空格拆分成数组,写完业务逻辑后还要记得输出换行。很多人因为输入解析写错,全题白做,特别可惜。

我的做题顺序是先快速看全部编程题,评估难度,先把最有把握的写完,再啃难题。每题先读一遍示例,理解输入输出格式。然后不管是暴力解法还是最优解法,先保证能跑通普通用例,至少把部分分拿到,再考虑优化。笔试判题一般是按测试用例百分比算分,只过一半用例也有分,千万别在一道题上死磕到没时间写别的。

写代码时养成好习惯:变量命名清楚,核心逻辑边写边注释,即使最终没有AC,面试官看你的代码也会有一个好印象。有些公司笔试是系统自动评分,但小红书这类注重工程化的团队在后续面试时可能会看到你的代码,代码风格不拉胯本身就是加分项。

4. 备考路线与工具链准备

4.1 从基础到专项的复习规划

针对小红书这种笔试,我把备考路线分成三个阶段。第一个阶段是补计算机基础,数据结构、算法、操作系统、网络这四门课有一个相对薄弱的,笔试就很难过,这个阶段大概两到三周,每天固定刷算法题并复习一个操作系统或网络专题。

第二个阶段是iOS专项突破。把上面提到的内存管理、Runtime、RunLoop、GCD、UI、网络、存储这些模块逐个过一遍,每个模块不只是看文档,要写demo验证。比如你学weak原理,就在Xcode里创建一个对象,用__weak引用它,再把它置nil,观察是不是自动变成nil;学KVO,就自己写一个派生类实现setter,看看不触发KVO时手动调用will/didChangeValueForKey能不能生效。知识只有亲手验证过,笔试遇到变体题才不容易慌。

第三个阶段是真题模拟和节奏训练。用牛客网的真题模拟环境做两到三套题,严格控制90分钟,模拟考场状态。我建议把刷题和笔试平台操作分开练习,代码在本地写完再贴到平台里也要跑一遍,很多平台对函数的调用方式有区别,提前适应能减少考场上的低级失误。

4.2 高效工具链:模拟器、抓包与调试

iOS开发调试离不开模拟器和真机。模拟器现在可以模拟不同的设备尺寸、系统版本,还能模拟网络状态弱网场景,笔试里问到的很多系统行为差异都能在模拟器里验证。不过模拟器不能完全代表真机,比如真实的内存压力、CPU调度、GPU渲染、传感器行为都有差异,所以备考时常备一台真机很有必要。

网络调试用Charles比较多。它做HTTPS抓包时需要安装并信任CA证书,然后在手机上安装描述文件并开启“允许完全信任”。这套流程里最容易踩的坑是:证书装好但系统版本升级后信任开关被重置,导致抓包看到一堆SSLHandshake错误。如果你在备考阶段要分析一个App的网络请求,用Charles辅助看请求头、参数、响应体,能帮你更好地理解客户端和服务端的交互逻辑。

开发和调试时要注意开发者模式和证书的管理。iOS开发者账号续费后证书需要更新,描述文件要及时重新下载安装,否则Xcode会提示“The provisioning profile is expired”。校招笔试不直接考这个,但实习面试和在线测试过程中可能需要你打包一个Demo给面试官看,如果这一步卡住会很尴尬。提前把开发者相关流程跑熟,属于那种“平时用不上、用上就救命”的技能。

4.3 原生iOS与跨平台技术的视野对比

小红书技术栈以原生为主,所以笔试重点是原生iOS。但作为iOS开发,了解一些跨平台方案是有必要的,因为你入职后可能要和做Android、前端的同事协作,也可能会接触到混编业务。

原生iOS和纯跨平台方案各有利弊。原生在系统API调用、性能、交互体验上优势明显,尤其是复杂的动画和大量图片列表场景,原生可以精确控制渲染细节。跨平台方案如Flutter、React Native、uni-app主打的是多端复用,开发效率高,适合业务快速迭代,但遇到系统级能力和疑难性能问题还是得回到原生层去处理。笔试里如果出现“App需要同时支持iOS和Android,你会怎么选型”这种开放题,你要能说出来:考虑团队能力、业务复杂度、性能要求和系统能力使用深度。

Android和iOS开发的区别也是面试官喜欢问的。iOS内存管理用ARC,Android用Java/Kotlin的GC;iOS的UI是UIKit的响应链,Android是View体系;iOS后台任务限制严格,Android有大量Service和广播机制。这类问题不要求你精通Android,但能讲清本质区别,会让面试官觉得你有对比思维和全局视野。

5. 常见问题与踩坑实录

5.1 笔试平台操作最容易翻车的几个点

笔试平台的操作失误有时候比知识盲区更致命。我总结了几条身边同学真实遇到过的坑,先写出来提醒大家。

第一,输入输出格式问题。有些编程题要求输出精确到小数点后两位,有些要求最后没有多余空格,这些细节不看清,格式错了直接判错。写完之后一定自己构造一两组边界用例测试,比如空数组、只有一个元素、数值上限。

第二,摄像头和屏幕共享异常。考试前检查摄像头是否被其他程序占用,浏览器是否开启了多个标签页,关闭所有弹窗和通知插件。如果考试中途摄像头断掉,系统可能会在后台记录异常标记,后续有可能被判定为作弊,特别冤。

第三,网络波动导致代码没保存。牛客网的代码编辑器会自动保存但也有延迟,别在最后五分钟大改代码,提交前确认代码已经在编辑框更新了。如果提交时间很紧张,优先保已通过用例的部分,不要在最后时刻重构。

5.2 iOS知识点的易错易混对照

笔试和面试里有很多iOS概念容易混淆,我把它们整理成一张速查表。表格里这些点几乎每年都有人错,备考时候反复看几遍,能有效减少失分。

易混概念核心区别笔试常见考法
weak vs assign vs unsafe_unretainedweak自动置nil;assign通常用于基本类型;unsafe_unretained不置nil会野指针选一个不安全的弱引用关键字
synchronous vs asynchronoussync会阻塞当前线程,async不会判断会不会死锁
frame vs boundsframe是相对父视图坐标;bounds是相对自身坐标旋转后frame变化而bounds不变的场景
深拷贝 vs 浅拷贝指针复制 vs 内容复制判断copy/mutableCopy结果
isKindOfClass vs isMemberOfClass前者判断是否属于类或子类;后者必须精确匹配给继承关系判断True/False
strong vs copycopy会复制一份新对象,可避免可变对象被外部修改NSString属性用copy的原因
onViewDidLoad vs viewWillAppear vs viewDidAppear生命周期各阶段的触发时机和次数判断某操作在哪个时机执行
堆 vs 栈堆需手动/ARC管理,栈自动管理全局变量、局部变量的存储位置
TCP vs UDPTCP可靠、面向连接;UDP不可靠、无连接视频通话为什么用UDP

除了这些概念题,笔试中还经常给一段代码让你判断输出。比如“NSMutableArray *arr = [NSMutableArray array]; arr = nil; 会不会崩溃”,答案是nil发消息在OC里是安全的,不会崩溃。但如果是向野指针发送消息就会崩溃,这两者很容易搞混。再比如“__block int a = 0; 在block里修改a能否生效”,这是可以的,但block被拷贝时a的存储位置会从栈上搬到堆上,所以用__block修饰的本质是让变量变成可以捕获和修改。

5.3 出分之后的复盘动作

笔试结束后别干等结果,把做错的题和没答上来的知识点复盘一遍。牛客网一般能查看每个测试用例的通过情况,结合自己的记忆,整理出一份错题集。这份错题集会在后面的面试中起到很大作用,因为如果笔试挂了,简历可能被锁一段时间,但如果笔试过了,面试官大概率会看你的笔试答题情况,你答得不好的题正好是面试时最可能被追问的点。

我个人的习惯是给每个考点建一个note文件,里面写三列:考点、我的理解、验证方式。比如写KVO的知识点,就先写下底层原理,再粘贴一段自己写的demo代码,再写“用instruments观察对象isa变化”的验证步骤。这样整理出来的笔记不是为了给别人看,而是确保自己真的能复述和动手验证。笔试前的最后一周,我只看这份note,不再去搜那些零散的文章金句。

写在最后的一些个人体会

回过头来看这次2023秋招小红书iOS开发岗第一批笔试,我最深的感触是:笔试考的不是你临时背了多少面经,而是你长期积累下来有没有形成一套完整的知识网络。iOS开发的知识面很宽,从语言底层到UI渲染,从并发编程到网络协议,每一块都像是拼图,缺少一块,面试和笔试遇到关联问题就会卡壳。

我自己的做法是把iOS的知识体系按“语言基础、内存管理、Runtime/消息机制、RunLoop、多线程、UI、网络、存储、性能优化、工程化”这十个模块去拆,每做一个模块的知识点都会配套写一个几行的小Demo跑一遍。笔试前每天再花半小时过一遍易错对照表,比临时刷题有效得多。

最后分享一个小技巧:遇到不会的笔试客观题,别乱猜,先用排除法把明显错误的选项去掉,再用“iOS系统实际行为”去反推哪个更合理。iOS很多机制是有内在一致性的,比如面向对象的继承决定了消息转发会逐级找父类,既然isa链是自底向上的,那么KVO通过动态子类来拦截setter也就顺理成章了。掌握这种底层逻辑,比记住一百个零散结论更能帮你稳稳拿分。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询