
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表示弱持有且對象釋放后自動置nilcopy會拷貝一份新對象assing對ObjC對象不安全對基本類型沒問題。筆試里最常考的循環引用場景有三個。第一個是block對象持有blockblock又捕獲了self就會形成self - block - self的環。解決辦法是用__weak __typeof(self) weakSelf self; 在block里再用strongSelf判空。第二個是delegatedelegate屬性要聲明為weak而不是strong否則兩個對象互相強持有就泄漏了。第三個是NSTimer或CADisplayLinktarget是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初始值為NM個任務并發最多同時執行幾個”。這個理解源碼就清楚了每次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和全局最大和maxcur小于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內存管理用ARCAndroid用Java/Kotlin的GCiOS的UI是UIKit的響應鏈Android是View體系iOS后臺任務限制嚴格Android有大量Service和廣播機制。這類問題不要求你精通Android但能講清本質區別會讓面試官覺得你有對比思維和全局視野。5. 常見問題與踩坑實錄5.1 筆試平臺操作最容易翻車的幾個點筆試平臺的操作失誤有時候比知識盲區更致命。我總結了幾條身邊同學真實遇到過的坑先寫出來提醒大家。第一輸入輸出格式問題。有些編程題要求輸出精確到小數點后兩位有些要求最后沒有多余空格這些細節不看清格式錯了直接判錯。寫完之后一定自己構造一兩組邊界用例測試比如空數組、只有一個元素、數值上限。第二攝像頭和屏幕共享異常。考試前檢查攝像頭是否被其他程序占用瀏覽器是否開啟了多個標簽頁關閉所有彈窗和通知插件。如果考試中途攝像頭斷掉系統可能會在后臺記錄異常標記后續有可能被判定為作弊特別冤。第三網絡波動導致代碼沒保存。牛客網的代碼編輯器會自動保存但也有延遲別在最后五分鐘大改代碼提交前確認代碼已經在編輯框更新了。如果提交時間很緊張優先保已通過用例的部分不要在最后時刻重構。5.2 iOS知識點的易錯易混對照筆試和面試里有很多iOS概念容易混淆我把它們整理成一張速查表。表格里這些點幾乎每年都有人錯備考時候反復看幾遍能有效減少失分。易混概念核心區別筆試常見考法weak vs assign vs unsafe_unretainedweak自動置nilassign通常用于基本類型unsafe_unretained不置nil會野指針選一個不安全的弱引用關鍵字synchronous vs asynchronoussync會阻塞當前線程async不會判斷會不會死鎖frame vs boundsframe是相對父視圖坐標bounds是相對自身坐標旋轉后frame變化而bounds不變的場景深拷貝 vs 淺拷貝指針復制 vs 內容復制判斷copy/mutableCopy結果isKindOfClass vs isMemberOfClass前者判斷是否屬于類或子類后者必須精確匹配給繼承關系判斷True/Falsestrong 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也就順理成章了。掌握這種底層邏輯比記住一百個零散結論更能幫你穩穩拿分。