復盤:從內存管理到Auto Layout的考點與實戰(zhàn))
1. 這套題為什么值得復盤1.1 校招筆試題型與考察目標金山辦公的2020校招iOS筆試題二當時在應屆生圈子里傳播度還挺高原因很簡單它不是那種靠死記硬背就能過的卷子。整張卷子覆蓋了Objective-C語言基礎、Foundation框架、內存管理、多線程、網(wǎng)絡層、UI布局以及少量的App工程化內容題型基本是單選、多選、簡答加一道編程題。從考察目標來看它想篩選的不是“刷過多少題”的人而是“有沒有真正寫過iOS App、踩過真實開發(fā)中的坑”的人。我當時拿到這套題的第一感受是它把面試官真正關心的東西藏在了題目背后。比如一道關于block循環(huán)引用的選擇題表面在考ARC下的內存管理實際是在考察你有沒有在項目中遇到過self被block持有導致的dealloc不執(zhí)行一道關于UITableViewCell復用的題目表面在考cellForRowAtIndexPath的寫法實際是在考察你有沒有處理過列表滑動卡頓和復用數(shù)據(jù)錯亂。筆試只是一個入口后面面試官會根據(jù)你的答案追問問的就是這些實際場景。所以這篇文章不只是對著題目念答案而是把每一類考點背后的考察邏輯、常見失分點、以及真實項目里怎么落地都拆開講。適合正在準備秋招或春招的應屆生也適合工作一兩年想跳槽、想系統(tǒng)梳理iOS知識體系的開發(fā)者。如果你還沒到投簡歷的階段提前看這篇也能幫你理清iOS開發(fā)需要掌握的核心知識脈絡。1.2 從“二”這個編號能讀出什么“二”說明這不是單獨的試卷而是一個題庫體系里的第二套。這種出題方式在校招里很常見一套題庫拆成多份卷子分發(fā)給不同批次或不同崗位方向的候選人題目會有重疊但組合方式不同。拆解“二”這套題時我關注的是它與筆試一可能的差異點——第二套通常在基礎上增加了更多進階題和應用場景題。比如金山辦公本身是做WPS Office的產(chǎn)品矩陣覆蓋Windows、macOS、iOS、Android還有云端協(xié)同。這種公司的iOS筆試題不會只考UI控件和API調用它會傾向考一些日常開發(fā)中真正影響體驗的點文件同步狀態(tài)下的數(shù)據(jù)一致性、編輯文檔時的內存占用、多任務切換時App的狀態(tài)保存。這也是為什么這套卷子里有不少題目都帶“場景前綴”——不是直接問“AFNetworking怎么用”而是先描述一個“用戶在斷網(wǎng)狀態(tài)下編輯文檔點擊保存后發(fā)生什么”的場景再讓你選合理的處理方案。對準備考試的人來說看懂“為什么考這道題”比“背下這道題的答案”更重要。你只有在平時開發(fā)時多問自己“這個功能在邊界條件下會怎樣”才能在校招筆試和面試里真正接住面試官的問題。2. 高頻筆試考點逐題拆解2.1 運行時、內存管理與KVO失分重災區(qū)iOS筆試里Objective-C的運行時和內存管理幾乎是必考板塊。這套題二在這方面大概占了四分之一的分值核心考點有三個消息機制、ARC下的對象生命周期、KVO/KVC的實現(xiàn)原理。先說消息機制。很多候選人能背出“objc_msgSend”這個函數(shù)名但題目只要拐個彎問“方法查找失敗后會發(fā)生什么”就有一半人答不上來。正確路徑是先查當前類的cache再沿繼承鏈逐級查找方法列表找不到就嘗試消息轉發(fā)動態(tài)方法解析、備用接收者、完整轉發(fā)三步全失敗才拋unrecognized selector。這個鏈路必須完整寫出來因為面試官接著就會問“你在項目里用過消息轉發(fā)嗎”如果你的答案是“沒用過”這道題最多只能拿一半分。我在項目里處理過最多的是“為NSNull添加安全的消息轉發(fā)”讓數(shù)組或字典里出現(xiàn)NSNull時不會直接崩而是返回nil。再說循環(huán)引用。筆試里常見的考法是給一段代碼問有沒有問題。比如block里使用self.property即使聲明了__weak如果在block內部又把這個weakSelf重新強引用依然會形成保留環(huán)。更隱蔽的是NSTimer強持有target如果你在dealloc里才invalidate那dealloc根本不會觸發(fā)timer永遠不釋放。正確做法是在viewWillAppear或viewDidAppear里創(chuàng)建timer在viewDidDisappear或viewWillDisappear里invalidate并且用weakSelf包裹selector。我把這種代碼在真實項目里調試過表現(xiàn)就是控制器的dealloc一直不調用內存一直漲除非殺掉App。KVO在筆試題里經(jīng)常和“觸發(fā)時機”掛鉤。一道經(jīng)典的變體題是在dealloc里移除KVO監(jiān)聽和自己手動removeObserver順序寫錯了會怎樣。正確理解是KVO觀察者不會強持有被觀察者但被觀察者釋放時如果觀察者還注冊著系統(tǒng)會crash。所以官方推薦在dealloc里調用removeObserver但必須保證remove操作不會觸發(fā)KVO回調時訪問已釋放對象。更細的點是對同一個key注冊兩次觀察者remove一次是崩潰的所以更好的做法是用統(tǒng)一的KVO工具類或使用Block KVO封裝。注意筆試里寫代碼題時即使題目沒有明確要求最好也畫出或寫出對象引用關系圖。解釋清楚“誰強引用了誰”“這個引用什么時候解除”比只給出代碼更能體現(xiàn)你對內存管理的理解。2.2 UI布局與Auto Layout從UIStackView到分屏適配這套筆試題的UI部分沒考太偏但有一個很有代表性的考點如何實現(xiàn)一個在橫豎屏、不同尺寸下都能保持間距一致的布局。當年筆試題里給了4個選項分別是手動計算frame、Autoresizing Mask、Auto Layout、UIStackView。選UIStackView的不一定對因為題目還加了一個前提——需要支持iOS 11及以上版本。很多候選人沒意識到UIStackView雖然在iOS 9就引入了但早期的UIStackView在動態(tài)增刪子視圖、嵌套布局時性能并不好而且它在iOS 11之前對隱藏子視圖的處理不夠完善。如果App最低支持版本是iOS 11那么UIStackView確實是最優(yōu)解如果最低支持版本更老就要考慮用Auto Layout加約束優(yōu)先級來模擬StackView的行為。這就是為什么我說“選框架要結合最低支持版本”而不是“哪個新選哪個”。還有一個隱藏考點是分屏適配。2020年iPadOS已經(jīng)支持多窗口和分屏所以金山辦公出這道題是在考察你是否有iPad適配經(jīng)驗。在iPad上做分屏布局不能再寫死寬度必須使用Size Classes配合TraitCollection來做響應式布局。我做過一個文檔閱讀器在iPad上分屏寬度只有320pt時工具欄上的按鈕要自動折疊成“更多”菜單實現(xiàn)方式就是根據(jù)horizontalSizeClass和寬度做動態(tài)判斷。關于Auto Layout性能筆試簡答題可能會問“約束多會不會影響性能”。正確的思路是約束的構建和計算成本主要在第一次layout時頻繁修改約束引起的layout pass才是性能瓶頸。優(yōu)化手段包括只更新變化的約束用IBOutlets持有需要變化的約束引用而不是每次都通過遍歷找到它、對列表項使用固定高度、避免在layoutSubviews里頻繁修改約束。記住不要在大列表里創(chuàng)建太多Auto Layout約束有時候“某幾個元素用frame其余用Auto Layout”混合布局反而更快。2.3 并發(fā)與網(wǎng)絡GCD、HTTPS與ATS跟并發(fā)相關的考點這套卷子主要集中在GCD的幾個核心問題上隊列類型、死鎖、線程安全。題目直接問“在主隊列上同步執(zhí)行一個任務會怎樣”答案是死鎖。這個例子很經(jīng)典但我在實際評審代碼時發(fā)現(xiàn)很多初級開發(fā)者只是背了結論沒真正理解死鎖產(chǎn)生的條件串行隊列 同步任務 當前正在執(zhí)行任務的隊列就是目標隊列。理解之后你就知道不只是主隊列任何串行隊列里嵌套同步派發(fā)到自身都會死鎖。另一個更隱蔽的坑是“使用dispatch_async到主隊列但在主隊列任務里又去等待一個信號量而信號量由另一個串行隊列的任務觸發(fā)那個串行隊列的任務又在等待這個主隊列任務”——多隊列互相等待也會死鎖這種場景在搭建路由跳轉等待層時容易遇到。網(wǎng)絡部分的高頻考點有三塊GET與POST的語義差別、HTTPS的握手流程、App Transport SecurityATS配置。在2020年的時候ATS幾乎已經(jīng)是強制項筆試題會問“如果服務器只支持HTTP在Info.plist里怎么配置”。正確做法是使用NSAppTransportSecurity的NSExceptionDomains只對特定域名開放HTTP而不是全局關閉ATS。但這里還有一個坑即使是配置了domain exception如果是自簽證書默認也會失敗必須配置NSExceptionAllowsInsecureHTTPLoads為YES或者是用NSURLSession的delegate方法實現(xiàn)更細粒度的證書校驗。筆試里還可能會出現(xiàn)URLSession和NSURLConnection對比的題。這個基本是老題了答案就是NSURLConnection在iOS 9后被標記廢棄NSURLSession才是官方推薦。但深層考點是NSURLSession支持后臺傳輸、斷點續(xù)傳、共享cookie存儲這些能力對于一個文檔類App至關重要——用戶在編輯完文檔后很可能切到后臺上傳任務還要繼續(xù)執(zhí)行這就必須用NSURLSession的background session。如果筆試題里描述了一個“用戶切到后臺文檔繼續(xù)上傳上傳完成后發(fā)送本地通知”的場景你要立刻聯(lián)想到background session和background tasks。3. 筆試中容易失分的邊界題3.1 多任務、后臺與電量優(yōu)化金山辦公的App有很多后臺使用場景比如打開文檔后切到其他App查資料再切回來。所以這套題的簡答題部分特意出了一道“App進入后臺后哪些操作會被系統(tǒng)限制”的題目。這道題每年都有大量考生答不完整或者把“后臺無限執(zhí)行”當作理所當然。正確答案要覆蓋幾個層面第一App進入后臺后只有短暫的時間現(xiàn)在約30秒可以繼續(xù)執(zhí)行代碼需要在applicationDidEnterBackground里做好狀態(tài)保存第二如果需要更長時間要用beginBackgroundTaskWithExpirationHandler申請后臺時間但系統(tǒng)不會保證給多少超時后必須立即結束第三對于音頻播放、定位、VoIP等特定場景可以聲明對應的UIBackgroundModes但濫用會被拒審。如果筆試里的場景是“用戶切后臺文章朗讀繼續(xù)播放”那這種場景可以聲明audio模式如果是“用戶切后臺下載任務繼續(xù)下載”那要用NSURLSession的background configuration。電量優(yōu)化是這套題比較超前的一個考點。2020年iPhone已經(jīng)支持低電量模式Low Power Mode系統(tǒng)會限制后臺刷新和部分動畫效果。筆試的考察點是你開發(fā)的App要如何感知低電量模式并關閉非必要功能。代碼上就是監(jiān)聽NSProcessInfoProcessInfo的lowPowerModeEnabled和PowerStateDidChangeNotification。我在做視頻類App時在低電量模式下會自動關閉自動播放、降低幀率、暫停預加載實測能明顯降低掉電速度。一個平時不關注系統(tǒng)狀態(tài)的開發(fā)者很難答出這種考點。3.2 系統(tǒng)狀態(tài)與BLE外設交互的陷阱這套筆試題里有一道比較偏的題目問的是“CoreBluetooth里系統(tǒng)級藍牙狀態(tài)和App級藍牙狀態(tài)如何區(qū)分”。這道題當年考的應屆生很多都懵了因為它不是常規(guī)iOS面試題但卻是智能硬件類App開發(fā)中會真實遇到的問題。系統(tǒng)級藍牙狀態(tài)指的是手機藍牙開關是否打開通過CBCentralManager的state屬性判斷。App級藍牙狀態(tài)指的是你的App是否有權限使用藍牙以及在藍牙開關變化后App內部的業(yè)務狀態(tài)。比如系統(tǒng)藍牙關閉后CentralManager會回調poweredOff但你的App里正在連接的peripheral對象并不會自動消失需要你主動更新UI并處理重連邏輯。更隱蔽的是用戶去設置里關閉了“允許App使用藍牙”的權限系統(tǒng)會回調unauthorized狀態(tài)但不會彈系統(tǒng)彈窗很多開發(fā)者沒有處理這個狀態(tài)導致App顯示“藍牙已連接”但實際收不到數(shù)據(jù)。與BLE相關的坑還有個經(jīng)典場景連接多個外設時只保留一個活動連接。CoreBluetooth允許同時連接多個外設但實際設備資源有限建議連接數(shù)不要超過同時支持的最大值。筆試題里如果問“如何控制必須連接完成一個設備后才連接下一個設備”正確答案是維護一個連接隊列在一個centralManager:didConnectPeripheral回調后再調用connect下一個peripheral。我在一個手持掃碼設備項目里用過這個思路穩(wěn)定性和性能都比并發(fā)連接好幾個外設要好。3.3 App簽名、證書與上架流程校招筆試題很少直接考證書和上架流程但金山辦公這套題確實出了相關簡答題原因可能是他們iOS團隊要招能獨立負責上線流程的人。我在復盤時覺得就算筆試不考這一塊面試也很容易被追問值得認真準備。核心考點有三個。第一開發(fā)證書和發(fā)布證書的區(qū)別開發(fā)證書用于模擬器和真機調試發(fā)布證書用于構建上傳App Store或企業(yè)分發(fā)兩者都關聯(lián)Bundle Identifier和團隊ID。第二描述文件Provisioning Profile的作用它把證書、設備開發(fā)階段和App ID綁定在一起App安裝時系統(tǒng)會校驗簽名和描述文件是否匹配且有效。第三App Store上架流程構建上傳用Xcode Organizer或Transporter上傳后在App Store Connect配置版本信息、截圖、審核備注然后提交審核。筆試時最容易丟分的是概念混淆。例如開發(fā)證書過期了能不能繼續(xù)真機調試答案是設備上的App會閃退因為簽名校驗失敗描述文件里注冊的設備列表發(fā)生變化時需要重新生成描述文件并重新簽名。還有證書吊銷后之前通過TestFlight安裝的App還能不能用——能用因為TestFlight驗證的是Apple服務器簽名不是開發(fā)者證書。這些都是真實開發(fā)中會遇到的情況如果只是背流程不看原理很難答對變體題。我建議準備校招的同學把這個流程親手走一遍注冊一個付費開發(fā)者賬號或者學校能給的教育優(yōu)惠從頭創(chuàng)建一個項目配置簽名跑真機再走一遍Archive和上傳。這個過程會踩很多坑比如Profile不匹配、證書在Keychain里丟失、導出ipa時簽名選錯。但走完一遍之后關于簽名和上架的所有筆試題目基本都擋不住你了。4. 從筆試題到面試如何把答案講成亮點4.1 架構模式與混合開發(fā)方案筆試的最后一題通常是設計題或開放題給你一個“實現(xiàn)XX功能”的需求讓你畫架構圖、寫核心代碼。金山辦公這套題二的壓軸題很有代表性讓考生設計一個“多人在線協(xié)同編輯一個文檔”的功能要求支持沖突處理、網(wǎng)絡狀態(tài)變化和離線緩存。很多考生看到這道題會先懵因為自己平時沒做過協(xié)同功能但面試官其實不是要求你把功能完整實現(xiàn)出來而是想看你有沒有基本的架構思維和信息論儲備。我的建議是答題時先明確幾個關鍵決策使用WebSocket還是HTTP輪詢、沖突解決用OTOperational Transformation還是CRDT、離線緩存用本地數(shù)據(jù)庫還是文件快照。你需要講清楚每種方案的優(yōu)缺點以及你根據(jù)場景選擇的原因而不是盲目堆技術名詞?;旌祥_發(fā)方案也是金山辦公這類公司比較關注的方向。他們的App可能有大量頁面由前端用H5實現(xiàn)iOS側做殼工程。筆試或面試常問“你了解哪些混合開發(fā)方案為什么選擇WebView而不是React Native或Flutter”。我的理解是如果頁面以展示型內容為主、更新頻率高用H5合適如果頁面交互復雜、需要高性能就用原生或Flutter如果團隊歷史包袱多可能用React Native兼容兩端邏輯。關鍵是你能說清楚“WebView和原生通信的機制是什么”——JSBridge原理、WKWebView的message handler、URL攔截和JavaScriptCore注入這些最??肌T谧黾軜嬵愒O計題時我比較推薦的回答框架是先描述清楚需求和使用場景再圍繞場景定技術選型接著畫出一張模塊拆解圖分層展示層、業(yè)務層、數(shù)據(jù)層、網(wǎng)絡層最后用幾句話說明數(shù)據(jù)流轉路徑。面試官想聽到的是“決策過程”而不是“一個完美的最終方案”所以你要敢做取舍敢說“這里我選擇犧牲實時性換取更低的實現(xiàn)成本”。4.2 用自動化與工程化能力拉高印象分雖然2020年的筆試題沒直接考自動化測試但我在復盤這套題時發(fā)現(xiàn)簡答題里有一道“你怎么保證你寫的代碼質量”的開放題答得好不好非常影響綜合評價。我見過不少候選人只會答“我寫完會自測”“我加日志調試”這種答案和沒答一樣。更好的思路是往工程化方向靠單元測試、UI測試、靜態(tài)分析、CI/CD流水線。比如談到iOS測試你可以講XCTest里如何對網(wǎng)絡層寫mock測試用OCMock或者自己寫Protocol做依賴注入你可以講XCTest UI測試在自動化回歸中的適用性和弊端——“UI測試不穩(wěn)定真機執(zhí)行慢所以只在關鍵路徑上覆蓋”。如果你用過fastlane可以講講它的match、scan、beta這些action對證書管理和自動化打包的幫助有多大。面試官聽到你熟練使用這些工具對你的評價會從“會寫功能”提升到“能獨立負責一個模塊的質量和發(fā)布”。還有一個很加分的點是你對構建流程有理解。很多應屆生只會點Xcode的Run不知道怎么打Debug和Release的差異不知道Archive和Export的區(qū)別。如果筆試題或面試提到“為什么模擬器上的App不能直接分發(fā)”正確的答案是模擬器構建的是x86_64架構的Mach-O真機需要arm64且模擬器包不包含完整的App簽名信息。如果你還能提前了解一下“我現(xiàn)在這個項目用了CocoaPods未來想遷移到SPM”就能和面試官聊很長時間。工程化的本質是降低協(xié)作成本和發(fā)布成本而不只是用幾個工具。5. 復習時間線、資料清單與我的心得5.1 三個月復習規(guī)劃參考如果你現(xiàn)在還有八九周就要參加校招筆試我建議按三個階段來準備。第一階段前三周打基礎把《Objective-C編程》和《Effective Objective-C 2.0》快速過一遍重點看內存管理、block、GCD、RunLoop這幾章把UIKit的常用控件和Auto Layout體系過一遍不要求能默寫所有API但要理解布局機制和生命周期。第二階段中間四周刷題加寫Demo搜集最近三年的iOS校招真題按知識點分類刷每道題都要弄清楚為什么對、為什么錯同時每天抽一小時寫一個完成度比較高的小功能比如“拍照并裁剪上傳”“實時音視頻聊天房間”把刷題時學到的技術點真正用出來。第三階段最后兩周模擬面試和復盤找個朋友互相問iOS問題或者自己對著錄音設備練“講清楚一個架構設計”把之前做過的Demo整理成項目和作品集梳理每段代碼解決了什么具體問題。這套題二的難度大概在中等偏上覆蓋的知識面比大多市面上流傳的iOS面試題集要寬。我的建議是不要只背題而是把每一道題當成一個知識樹的根節(jié)點向上追原理、向下追實現(xiàn)、旁支追場景。比如一道“UITableView卡頓怎么優(yōu)化”的題你要能向上扯出RunLoop和屏幕刷新機制向下能說出估算高度、異步繪制、圖層混合等優(yōu)化手段旁支能聊到SDWebImage怎么管理圖片緩存。能說成這樣筆試面試都不會差。5.2 我踩過的坑和一點個人心得我復盤這套題的時候想起自己當年準備校招時踩過的一個坑過度看重“冷門偏題”把大量時間花在鉆研Core Animation的底層渲染和音視頻解碼這些知識上結果基礎題反而因為手生丟了分。后來我?guī)嵙暽鷷r發(fā)現(xiàn)很多人也會犯同樣的錯總覺得考官會出偏題壓分實際上筆試題的區(qū)分度主要靠“基礎題你是否掌握得足夠扎實”和“場景題你是否能形成自己的判斷”。另一個坑是“看得多、寫得少”。看別人的iOS面試題解析、刷LeetCode和算法題確實有用但它替代不了你親手寫代碼。金三銀四秋招季我見過太多候選人簡歷上寫著“熟悉iOS內存管理”但真讓他處理一個循環(huán)引用崩潰半天定位不到是block還是delegate的問題。建議你除了筆試準備一定要親手維護一個自己的Demo項目定期加功能、換架構、寫測試遇到問題用真機調試、用Instruments看內存和CPU這樣才能在筆試和面試時給出有底氣的答案。最后校招只是職業(yè)生涯的起點。就算某套筆試題沒答好也沒關系把錯題整理成自己的知識庫比拿一個offer更有長期價值。金山辦公這套題二給我最大的啟發(fā)不是那些考點本身而是讓我意識到iOS開發(fā)是一個“場景驅動”的領域掌握了再多的API脫離真實場景都記不牢。真正有效的學習方式是拿一個真實需求從方案設計到編碼實現(xiàn)再到上線維護完整走一遍。這個過程積累下來的經(jīng)驗和判斷力才是通過筆試、通過面試、以及未來在團隊里立足的根本。