2021- iOS開發者一份你一定會被問到的面試題(附參考答案) 提問:

當您準備 iOS 技術面試時,重要的是要了解您可能會被問到哪些主題以及對經驗豐富的 iOS 開發人員的期望。許多公司使用這些問題和主題(以一種或另一種形式)來衡量 iOS 候選人的經驗水平。它們涵蓋了 iOS 開發的各個方面,旨在廣泛瞭解該平臺。畢竟,高級開發人員應該能夠從頭到尾發佈完整的 iOS 產品。但在擁有大型 iOS 開發團隊(想想 25 人以上)的大公司中,專業化和專注於特定問題(如網絡)的深入知識也會發生。這絕不是一份詳盡的清單,但它可以幫助您爲即將到來的 iOS 技術面試做好準備。

如果你正在跳槽或者正準備跳槽不妨動動小手,添加一下咱們的交流羣1012951431來獲取一份詳細的大廠面試資料爲你的跳槽多添一份保障。

提問:

  1. Swift 的主要特點和優點或缺點是什麼?
  2. 什麼是 iOS 應用程序,您的代碼在哪裏適合它?
  3. iOS 上的內存管理是如何處理的?
  4. 什麼是MVC?
  5. 你對單身人士瞭解多少?你會在哪裏使用,你不會在哪裏?
  6. 解釋一下委託和 KVO 之間的區別?
  7. iOS 應用中常用的設計模式有哪些?
  8. 除了常見的 Cocoa 模式,你還知道哪些設計模式?
  9. 解釋和展示 SOLID 原則的例子?
  10. 在 iOS 上實現存儲和持久化有哪些選擇?
  11. 在 iOS 上實現網絡和 HTTP 有哪些選擇?
  12. 如何以及何時在 iOS 上序列化和映射數據?
  13. 在 iOS 上佈局 UI 的選項有哪些?
  14. 如何優化動態調整大小的表格或集合視圖的滾動性能?
  15. 你如何在iOS上執行異步任務?
  16. 你如何管理依賴關係?
  17. 你如何在 iOS 上調試和分析代碼?
  18. 你有TDD經驗嗎?你如何在 iOS 上進行單元和 UI 測試?
  19. 模擬、存根和假貨之間有什麼區別?
  20. 您是否進行代碼審查和/或結對編程?
  21. 什麼是 FRP(Functional Reactive Programming)及其在 iOS 平臺中的地位?
  22. 你知道哪些 iOS 架構有這麼大的規模?

在下面的部分中,我將詳細介紹每個問題、其背後的推理、預期答案以及可能會給面試官帶來危險的答案。在適用的情況下,問題有進一步閱讀部分,您可以在其中找到與它們相關的更多材料的鏈接和參考。

1.Swift 的主要特點和優點或缺點是什麼?

這聽起來像是一個初學者的問題,但事實並非如此。有時可能會要求評估您使用其他語言的經驗以及您對所使用語言的更廣泛理解及其優點、缺點和侷限性。

預期答案:

TLDR:主要的 Swift 特性 - 靜態類型、協議、引用類型、值類型、選項、泛型。

Swift 是一種強類型語言,這可能是它最大的特點,同時也是優點和缺點。靜態類型允許存在協議、泛型和選項,並幫助您進行開發。靜態類型給你很多編譯時警告和編譯錯誤,但提供了更好的運行時安全性和確定性(可選、var/let、泛型或具體類型等)。這是該語言提供的最大優勢之一。在以下場景中擁有嚴格的類型安全是最有幫助的:

  • 當您構建客戶端應用程序並且需要更嚴格的明確性而不是動態性和靈活性時
  • 當您在這樣的環境中工作時,您希望限制經驗不足的開發人員(初學者和初級人員)擁有過多的權力並讓自己陷入困境
  • 當您需要重構代碼並且編譯器可以幫助您正確正確地編寫代碼時

所有這些恰好是 iOS 開發人員構建的大多數面向客戶的應用程序。

同時,當您構建需要更多靈活性的東西(例如構建庫或框架)時,靜態類型可能過於嚴格。在這方面,Objective-C 可能是更好的選擇,因爲它比 Swift 具有更好的元編程功能。(雖然可以說此時 Objective-C 已經過時了,Apple 平臺的所有開發都應該在 Swift 中完成)

注意點:

只要您能闡明每個功能提供的內容,即協議和泛型實際上允許您在代碼中做什麼,您就可以了?但同樣,與嚴格的類型系統相比,這些可以說是次要的語言功能。

這個問題的進一步閱讀:

2.什麼是 iOS 應用程序,您的代碼在哪裏適合它?

這是一個以一種或另一種形式提出的宏觀問題,以衡量您對 iOS 應用程序是什麼的理解,以及您編寫的代碼在其中的位置以及在整個 iOS 系統中的位置。

預期答案:

我們可能認爲我們構建的應用程序很特別,因爲它們涵蓋了一個獨特的用例。但是您典型的 iOS 應用程序只是一個巨大的、美化的運行循環。它等待用戶輸入並被外部信號中斷,例如電話、推送通知、家庭手勢/按鈕按下和其他應用程序生命週期事件。唯一的區別在於,它不僅僅是一個簡單的主循環函數,每次用戶點擊您的應用程序圖標時都會啓動它,它具有更高級別的抽象,開發人員可以使用UIApplicationAppDelegateSceneDelegate

您爲實現應用程序的業務邏輯而編寫的其餘代碼放置在該主循環通過AppDelegate或委託給我們的應用程序的“觸發點”中的某個位置SceneDelegate。在 iOS 13AppDelegate負責接收應用程序的所有外部事件並啓動 UI 之前;但是從 iOS 13 開始,所有與 UI 相關的邏輯都移到了 SceneDelegate。

而已。簡單的。您爲應用編寫的代碼可以像方法/函數調用一樣簡單,也可以像 VIPER 架構一樣複雜。這是你的選擇。

注意點:

通常,開發人員將 iOS 應用程序視爲他們編寫的 MVC 代碼以及實現的複雜細節,這是事實。但是如果你退後一步看大局,你會看到 iOS 應用程序真正是什麼——一個運行循環。

這個問題的進一步閱讀:

3.iOS 中的內存管理是如何處理的?

內存管理在任何應用程序中都非常重要,尤其是在具有內存和其他硬件和系統限制的 iOS 應用程序中。本題涉及ARC、MRC、引用類型和值類型。

預期答案:

Swift 使用自動引用計數 ( ARC )。這在 Swift 和 Objective-C 中在概念上是一樣的。ARC 跟蹤對類實例的強引用,並在您將類(引用類型)的實例分配或取消分配給常量、屬性和變量時相應地增加或減少它們的引用計數。它釋放引用計數降至零的對象使用的內存。ARC 不會增加或減少值類型的引用計數,因爲在賦值時,這些被複制。默認情況下,如果您不另行指定,則所有引用都將是強引用。

注意點:

這是每個 iOS 開發者都必須知道的!由於 iOS 應用程序中的內存管理不善,內存泄漏和應用程序崩潰非常普遍。

這個問題的進一步閱讀:

4.什麼是MVC?

哦,好老的MVC。這是 Apple 不斷推給 iOS 開發人員的基本設計模式。很可能每個面試官都會問這個,不管你是申請高級職位還是初級職位。不過,您作爲大四學生的回答會有所不同。

預期答案:

MVC代表模型視圖控制器。這是 Apple 選擇的一種軟件設計模式,作爲 iOS 應用程序開發的主要方法。模型代表應用數據;視圖在屏幕上繪製東西;控制器管理模型和視圖之間的數據流。模型和視圖從不直接相互通信,而是依靠控制器來協調通信。這種設計模式被 Apple 從其最初的 SmallTalk 實現演變成其他的東西 。

iOS 應用程序中每個 Apple MVC 層的典型表示是:

MVC 是一種很棒的通用設計模式,但作爲高級開發人員,您應該知道它只是視圖層的一種設計模式,單獨使用它會限制您的架構,並經常導致臭名昭著的“大規模視圖控制器”問題。

大規模視圖控制器是代碼庫的狀態,其中許多邏輯和責任被推入不屬於那裏的視圖控制器。這種做法會使您的代碼僵化、臃腫且難以更改。還有其他設計模式可以幫助您解決這個問題,例如 MVVMMVPCoordinator。還有一些架構,例如VIPERRIB,專門用於擴展 iOS 代碼和避免 Massive View Controller 問題。

儘管 Apple 一直告訴我們 MVC 是一切,但要更好地瞭解並堅持SOLID原則。

注意點:

您絕對必須知道什麼是 MVC,因爲它是任何 iOS 開發的基礎。不過,探索替代方案和附加功能,例如 MVVM、MVP、VIPER 和 RIB。

這個問題的進一步閱讀:

5.你對Singleton瞭解多少?你會在哪裏使用,你不會在哪裏?

Singleton 是許多 OOP 語言中常用的設計模式,Cocoa 將其視爲“Cocoa 核心能力”之一。這個問題出現在面試中,以衡量您對Singleton的體驗,或者瞭解您是否擁有 iOS 以外的其他方面的背景。

預期答案:

Singleton是一個類,無論您請求多少次,它都只返回一個相同的實例。

單例有時被認爲是一種反模式。使用單例有多個缺點。主要是全局狀態、對象生命週期和依賴注入。當您只有一個實例時,很容易直接在任何地方引用和使用它,而不是將它注入到您的對象中。這會導致代碼中不必要的具體實現耦合,而不是使用接口抽象。

“Singleton”的另一個副作用是全局狀態。單例通常可以實現全局狀態共享,並扮演每個對象用來存儲狀態的“公共包”的角色。當這種不受控制的狀態被某人覆蓋或刪除時,這會導致不可預測的結果和錯誤或崩潰。

注意點:

儘管在某些語言和平臺中單例被認爲是好的,但它們實際上是一種反模式,應該不惜一切代價避免。

這個問題的進一步閱讀:

6.Delegate和 KVO 之間有什麼區別?

通過這個問題,您的面試官正在評估您對 iOS 中使用的不同消息傳遞模式的瞭解。

預期答案:

兩者都是在對象之間建立關係的方法。Delegate是一種一對一的關係,其中一個對象實現委託協議;另一個使用協議定義的方法向它發送消息。KVO是一種多對多關係,其中一個對象廣播一條消息,一個或多個其他對象偵聽它並做出反應。KVO 不依賴於協議。KVO 是反應式編程(RxSwiftReactiveCocoa等)的 第一步和基本塊

注意點:

經驗豐富的開發人員應該知道兩者之間的區別,以及在哪裏使用它們。

這個問題的進一步閱讀:

7.iOS 應用中常用的設計模式有哪些?

這個問題在所有級別職位的面試中都很常見,除了初級職位。使用 iOS 平臺的開發人員應該熟悉 iOS 上常用的技術、架構和設計模式。

預期答案:

構建 iOS 應用程序時典型的常用模式是 Apple 在其 Cocoa、Cocoa Touch、Objective-C 和 Swift 文檔中提倡的模式。這些是每個 iOS 開發人員都學習的模式。Apple 將它們稱爲“核心競爭力”設計模式。它們包括MVCSingletonDelegateObserver

注意點:

當面試官問這個問題(以一種或另一種形式)時,他正在尋找 MVC 之外的東西。因爲 MVC 是首選設計模式,所以期望每個 iOS 開發人員都知道它。但是,他們想從您那裏聽到的是我們通常開箱即用的其他內容。

這個問題的進一步閱讀:

8.除了常見的 Cocoa 模式,你還知道哪些設計模式?

這是一個高級問題,面試官在你面試高級或建築師職位時會問這個問題。期望您瞭解 iOS 應用程序中使用的更多實用設計模式,而不是前面問題中涵蓋的基本設計模式。準備好回憶一堆四人組模式和其他類似模式。

設計模式本身就是一個很大的話題(它們在我的書中有更好的介紹),所以在這裏我將只總結那些我在 iOS 代碼庫中常見的內容。

預期答案:

除了常用的 MVC、Singleton、Delegate 和 Observer 模式之外,還有許多其他模式非常適用於 iOS 應用程序:Factory MethodAdapterDecoratorCommandTemplate

工廠方法用於替換類構造函數,抽象和隱藏對象初始化以便在運行時確定類型,以及隱藏和包含switch/if確定要實例化的對象類型的語句。

適配器是一種設計模式,顧名思義,它可以幫助您使一個對象的接口適應另一個對象的接口。當您嘗試調整無法更改爲您的代碼的第三方代碼時,或者當您需要使用具有不方便或不兼容的 API 的東西時,通常會使用此模式。

裝飾器是另一個類的包裝器,可增強其功能。它環繞着你想要裝飾的東西,實現它的接口,並將發送給它的消息委託給底層對象,或者增強它們或提供它自己的實現。

命令是一種設計模式,您可以在其中實現一個對象,該對象表示您想要執行的操作。該操作可以有自己的狀態和邏輯來執行它所做的任務。這種設計模式的主要優點是您可以對用戶隱藏操作的內部實現,您可以爲其添加撤消/重做功能,並且您可以在稍後的時間點(或根本不)執行操作而不是立即創建操作。

模板是一種設計模式,其主要概念是擁有一個基類,該基類概述了需要完成的工作的算法。基類有幾個抽象方法,需要由它的具體子類來實現。這些方法稱爲鉤子方法。模板方法類的用戶僅使用實現算法步驟的基類進行交互;這些步驟的具體實現由子類提供。

注意點:

當您剛開始使用 iOS 平臺時,僅堅持使用 MVC、單例、委託和觀察者模式是沒問題的,但是對於高級的東西,您需要更深入地研究更抽象和更高級的東西,例如四人組 OOP 設計模式。它們非常有用,可以使您的代碼庫更加靈活和可維護。

這個問題的進一步閱讀:

9.解釋和展示 SOLID 原則的例子?

SOLID 原則是相對古老但非常有用的概念,可以應用於任何語言的任何 OOP 代碼庫。觀看鮑勃叔叔關於該主題的一些演講,以充分了解他們背後的歷史。

在 YouTube 上:Bob Martin 面向對象和敏捷設計的 SOLID 原則

不幸的是,SOLID原則本身就是一個很大的話題(它們在我的書中也有更好的介紹),所以在這裏我將只給出它們的概述。

預期答案:

SOLID代表單一職責原則開放/封閉原則Liskov 替換原則接口隔離原則依賴倒置原則。這些原則相互補充和支持,是您可以爲代碼採用的最佳通用設計方法之一。讓我們來看看它們中的每一個。

單一職責原則(SRP)是團隊中最重要的原則。它指出每個模塊應該只有一個更改的責任和理由。SRP 從小的具體和特定案例開始,例如一個類和/或一個只有一個目的並且僅用於一件事的對象。

開放/封閉原則 (OCP)規定您的模塊應該對擴展開放,但對修改關閉。這是聽起來很容易的事情之一,但當您開始思考它的含義時,有點難以理解。實際上,這意味着在編寫代碼時,您應該能夠通過使用接口、抽象和依賴注入實現對象的繼承、多態和組合來擴展對象的行爲。

Liskov 替換原則 (LSP)指出,程序中的對象應該可以替換爲其子類型的實例,而不會改變該程序的正確性。這意味着當您從類或抽象類繼承或實現接口(協議)時,您的對象應該是可替換和可注入的,無論您使用哪個接口或類的子類。這個原則通常被稱爲契約設計,或者在 Swift 社區的後期,被稱爲面向協議的編程。這個原則的主要信息是你不應該違反你的接口從承諾到實現的子類的約定,並且通過子類化,這些子類可以在以前使用超類的任何地方使用。

接口隔離原則 (ISP)說,許多特定於客戶端的接口比一個通用接口要好。它還指出,不應強迫任何客戶端依賴和實現它不使用的方法。這意味着當你創建你的類實現的接口(協議)時,你應該爭取並依賴抽象而不是特異性,但直到它成爲一種浪費,你必須實現一堆你的新類沒有的方法甚至使用。

依賴倒置原則 (DIP)指出,“依賴於抽象,而不是具體化。” 展示此原則的最佳示例是依賴注入 (DI) 技術。使用依賴注入技術,當你創建一個對象時,你在它的初始化或配置時提供和注入它的所有依賴項,而不是讓對象爲自己創建或獲取/找到它的依賴項。

注意點:

SOLID 原則是良好的 OOP 設計的基石。應用這些原則將幫助您構建更好、更易於維護的軟件。如果您正在申請 iOS 高級職位,強烈建議您精通它們。

這個問題的進一步閱讀:

10.在 iOS 上實現存儲和持久化有哪些選擇?

面試官問這個問題是爲了讓你瞭解你有哪些工具和方式可以在 iOS 上存儲和持久化數據。

預期答案:

通常有以下幾種方式來存儲數據,從簡單到複雜的順序:

  • 內存中的數組、字典、集合和其他數據結構
  • NSUserDefaults/鑰匙串
  • 文件/磁盤存儲
  • 核心數據,領域
  • SQLite

內存中的數組、字典、集合和其他數據結構非常適合中間存儲數據,或者如果不需要持久化數據。

NSUserDefaults/Keychain是簡單的鍵值存儲。一個是不安全的,另一個是安全的。

文件/磁盤存儲是一種使用NSFileManager向/從磁盤寫入數據(序列化或非序列化)的方式

Core DataRealm是簡化數據庫工作的框架。

SQLite是一個關係型數據庫,當你需要實現複雜的查詢機制而 Core Data 或 Realm 不會削減它時,它是很好的。

注意點:

您應該瞭解在 iOS 上存儲數據的不同方式及其優缺點。不要將自己侷限於一種您習慣的解決方案(例如 Core Data)。知道什麼時候一個比另一個更可取。

這個問題的進一步閱讀:

11.哪些選項可用於 iOS 上的網絡和 HTTP?

如今,每個應用程序都使用網絡從 API 和其他外部資源獲取數據。許多應用程序在未連接到互聯網時是無用的。每個 iOS 開發人員都應該知道他們可以使用什麼來構建應用程序的服務/網絡層。

預期答案:

在 iOS 中有幾種實現HTTP網絡的選項。您可以使用舊的NSURLSession,但除非您將其抽象得足夠好,否則使用它可能會令人生畏。另一種選擇是在它周圍使用包裝器庫。iOS 上最流行的解決方案是Alamofire

一般來說,如果您有一個小團隊,您可能希望依賴開源解決方案,例如 Alamofire,它爲您抽象出大量樣板代碼;但是如果你在一個大團隊中並且可以節省資源,你會希望對數據如何傳入/傳出服務器有更多的控制權,並使用 NSURLSession 自己實現它。

高級開發人員應該記住,在 iOS 應用程序中構建網絡層不僅意味着處理 HTTP 請求,還意味着實現您的代碼所做的與此相關的整套任務:HTTP 網絡、數據序列化和數據映射。

注意點:

現在,NSURLSession 和 Codable 是 iOS 上用於網絡的兩種主要技術,但瞭解開源解決方案(例如 Alamofire)也是有益的。

這個問題的進一步閱讀:

12.如何以及何時在 iOS 上序列化和映射數據?

數據序列化是構建 iOS 應用程序時的一項常見任務。面試官問這個問題是想看看你是否知道它適合哪裏,是否知道處理數據時所需的任務,無論是網絡還是存儲數據。

預期答案:

有兩種最常見的場景需要在 iOS 應用程序中序列化和映射數據:在網絡層接收或發送數據(例如 JSON 或 XML 或其他東西),以及在存儲層(NSData)中持久化或檢索模型,NSManagedObject)。

每次您從後端 API 接收 JSON 或 XML 或任何其他響應類型的響應時,您很可能會以 JSON 或二進制或其他“不方便”的格式獲得它。要處理收到的數據,您需要做的第一件事是將其序列化爲您的應用程序可以理解的內容。在最簡單和基本的層面上,這將是一個字典或一個包含來自該響應的其他字典、數組和基元的對象數組。NSJSONSerialization 負責解決這個問題。下一步是將該數據映射到應用程序的域模型中。這些將是應用程序其餘部分要使用的模型對象或結構。您可以手動完成,也可以使用CodableApple 提供的協議或使用 Mantle 或 SwiftyJSON 等庫。數據和序列化/映射的流程是:binary data->json-> NSDictionary/NSArray-> your domain model objects

同樣,在存儲層中,您需要將數據序列化並映射到您的自定義域模型對象和從您的自定義域模型對象映射到您的存儲理解的格式。讀取數據的“映射”鏈:db-> raw data format-> custom domain models; 和寫作:custom domain models-> raw data format-> db。您將在這裏使用 NSManagedObject 或 NSCoding 或 Codable 協議來實現這一點。

注意點:

這裏的主要危險信號是沒有意識到在使用 iOS 應用程序的網絡和存儲層時需要進行這些數據操作。事情不會“自動”發生,使用原始 NSDictionaries 也不合適且可維護。

這個問題的進一步閱讀:

13在 iOS 上佈局 UI 的選項有哪些?

當您需要在 iOS 上解決不同的 UI 挑戰時,瞭解在屏幕上佈置內容的選項至關重要。這個問題有助於衡量您如何在屏幕上放置和對齊視圖的知識。在回答這個問題時,你至少應該提到 CGRect、Fframes 和 AutoLayout 和 SwiftUI,但最好提到其他選項,例如 Texture (ASDK)、ComponentKit 和其他 Flexbox 和 React 在 iOS 上的實現。

預期答案:

在屏幕上佈置視圖的首選選項是舊的 CGRect Frames 和 AutoLayout。框架以及自動調整大小的遮罩,過去在 iOS 6 之前使用過,現在不是首選選項。框架太容易出錯且難以使用,因爲很難計算各種設備的精確座標和視圖大小。

從 iOS 6 開始,我們有了 AutoLayout,這是當今的首選解決方案,也是 Apple 更喜歡的。AutoLayout 是一種技術,可幫助您以聲明方式定義視圖之間的關係(稱爲約束),讓框架計算 UI 元素的精確框架和位置。

在 iOS 13 中,Apple 引入了一種佈局視圖的新方法 - SwiftUI,這是一種聲明式方法,支持使用 Combine 進行 FRP(功能反應式編程)數據綁定。FRP 和聲明式 UI 並不是新概念,但 SwiftUI 和 Combine 是 Apple 支持它的新框架。SwiftUI 的聲明性質允許您非常簡潔地聲明您的 UI 元素,然後通過數據綁定聲明 UI 的哪些部分,例如文本標籤,以更新哪些數據模型更改。實際上,它允許你做以前用 RxSwift 已經可以做到的事情,但現在用 Apple 框架。

佈局視圖還有其他選項,例如 ASDK(Texture)、ComponentKit 和 LayoutKit,其中一些或多或少受到 React 的啓發,而另一些則以不同的方式解決佈局異步性。這些替代方案在某些情況下非常有用,例如,您需要構建高度動態且快速的表視圖和集合視圖。AutoLayout 並不總是完美的,知道有其他選擇總是好的。

注意:我們將在未來看到 SwiftUI 如何證明自己解決複雜的 UI 問題和複雜的異步 UI 佈局問題,在撰寫本文時,它是一項非常新的技術。

注意點:

至少不要提到 AutoLayout 以及框架很難正確的事實,這對你的面試官來說是一個危險信號。如今,除非有必要(例如,當您進行瘋狂繪圖時),否則沒有理智的人會進行 CGRect 框架計算。

這還不是危險信號,但請提及 SwiftUI,這可能是 Apple 在未來幾年推動我們的目標。

這個問題的進一步閱讀:

14.如何優化動態大小的表或集合視圖的滾動性能?

面試中與 UITableView 問題一起的重要問題之一是關於滾動性能。

預期答案:

滾動性能是 UITableViews 的一個大問題,而且通常很難做到正確。主要難點是單元高度計算。當用戶滾動時,每個下一個單元格都需要計算其內容和高度才能顯示。如果您進行手動框架視圖佈局,那麼它的性能會更高,但挑戰在於正確計算高度和大小。如果您使用 AutoLayout,那麼挑戰是正確設置所有約束。但即使是 AutoLayout 本身也可能需要一些時間來計算單元格高度,並且您的滾動性能會受到影響。

滾動性能問題的潛在解決方案可能是:

  • 自己計算單元格高度
  • 保留一個用內容填充的原型單元格並使用它來計算單元格高度

或者,您可以採取完全激進的方法,即使用不同的技術,例如 ASDK(紋理)。ASDK (Texture) 專爲具有動態內容大小的列表視圖而設計,並針對在後臺線程中計算單元格高度進行了優化,使其具有超強的性能。

這個問題的進一步閱讀:

15.你將如何在 iOS 上執行異步任務?

如今,多線程是任何客戶端、面向用戶的應用程序的重要組成部分。這個問題可以在網絡環境中提出,也可以作爲關於 GCD 或異步開發的獨立問題提出。

預期答案:

現在在 iOS 上,異步任務的首選解決方案是 NSOperations 和 GCD 塊。Grand Central Dispatch 是一種與多個後臺隊列一起工作的技術,這些隊列反過來確定哪個後臺線程處理工作。主要的是,這是從你那裏抽象出來的,這樣你就不必擔心了。NSOperation 是 GCD 之上的 OOP 抽象,它允許您執行更復雜的異步操作,但是您可以使用 NSOperations 實現的所有操作都可以使用 GCD 完成。許多 Cocoa 框架在底層使用 GCD 和/或 NSOperations(例如 NSURLSession)。

有使用第三方庫的幫助處理異步工作的替代方法。最著名的是 Promises (PromiseKit)、RxSwift 和 ReactiveCocoa。RxSwift 和 ReactiveCocoa 尤其擅長建模需要在後臺完成並在線程之間協調的時間和工作的異步性質。

注意點:

每個 iOS 開發人員都應該瞭解的有關異步工作的基礎知識是 GCD 和 NSOperations。RxSwift 和 Promises 是高級概念,但高級開發人員應該知道它們。

這個問題的進一步閱讀:

16.你如何管理依賴關係?

依賴管理是每個 iOS 項目中的一項重要任務。這個問題衡量您對問題及其解決方案的理解。

預期答案:

幾年前,我們在 iOS 上沒有任何依賴管理器,不得不將第三方代碼複製粘貼和拖放到我們的項目中或使用 Git 子模塊。隨着我們的代碼庫和依賴項的增長,這些方法被證明是難以管理的。

現在我們有其他依賴管理器可供選擇:CocoaPods、Carthage 和 Swift Package Manager。

到目前爲止,最具統治力和最強大的是CocoaPods。我是本着 Ruby Bundler gem的精神構建的,它本身就是一個 Ruby gem。它的工作方式是安裝 gem,Podfile在項目的根目錄中創建,聲明要使用的 pod(庫),然後運行pod install. 而已。

使用Carthage,您可以創建一個名爲的依賴聲明文件,Cartfile但與 Cocoapods 不同的是,您需要進行 Xcode 項目設置才能使其工作。

Swift Package Manager是任何 Swift 項目依賴管理的未來,但它只支持庫和框架,不能用於生成 iOS 目標,儘管 iOS 目標可以依賴於 SPM 構建的模塊。

注意點:

每個 iOS 開發人員都應該瞭解爲什麼將第三方庫複製粘貼到您的代碼庫中會導致維護噩夢,因爲多個庫可能依賴於另一個庫的兩個不同版本,從而導致不匹配以及編譯和運行時問題。

這個問題的進一步閱讀:

17.你如何在 iOS 上調試和分析代碼?

沒有人會寫出完美的代碼,開發人員需要調試他們的代碼並分析應用程序的性能和內存泄漏。

預期答案:

在 iOS 應用程序中 總是有NSLogging 和printing。您可以使用 Xcode 設置斷點。對於單個代碼段的性能,您可以使用 XCTest 的 measureBlock。

您可以使用Instruments. Instruments 是一種分析工具,可幫助您分析應用程序並在運行時查找內存泄漏和性能問題。

這個問題的進一步閱讀:

18.你有TDD經驗嗎?你如何在 iOS 上進行單元和 UI 測試?

儘管從歷史上看,iOS 社區在 TDD 上並不大,但由於工具的改進和其他社區(例如很久以前接受 TDD 的 Ruby)的影響,它現在變得越來越流行。

預期答案:

TDD 是一種技術和學科,您首先編寫失敗的測試,然後再編寫使它們通過的生產代碼。測試驅動生產代碼的實現和設計,幫助您只編寫通過測試實現所需的代碼,不多也不少。該學科起初可能令人生畏,您不會立即看到這種方法的回報,但如果您堅持下去,從長遠來看,它會幫助您更快地前進。它在幫助您進行重構和代碼更改方面特別有效,因爲在任何給定時間,您都有測試的安全網來告訴您是否有問題發生,或者在您更改時一切是否仍然正常。

最近,Apple 對 XCTest 框架進行了改進,使我們的測試更容易。他們還對 Xcode (XCUITest) 中的 UI 測試進行了大量改進,因此現在我們有一個很好的編程界面來與我們的應用程序交互並查詢我們在屏幕上看到的內容。或者,您可以使用 KIF、iOSSnapshotTestCase、EarlGrey 等框架。

關於單元測試,也有多種選擇,但最流行的兩個是 XCTest 和 Quick 和 Nimble。

XCTest是由 Apple 構建的類似 xUnit 的測試框架。這是他們推薦使用的,它與 Xcode 的集成度最高。

Quick是一個類似於 RSpec 的 BDD 框架,可幫助您根據行爲而非“測試”來描述規範/測試。RSpec 的粉絲非常喜歡它。

Nimble是一個匹配器庫,可與 XCTest 或 Quick 一起使用以斷言您的測試/規範中的期望。

注意點:

越來越多的團隊和公司採用 TDD,它已成爲 iOS 開發過程中的重要組成部分。如果您不想被拋在後面,請加入它並學習如何測試驅動您的代碼。

這個問題的進一步閱讀:

19.mocks、stubs和fakes之間有什麼區別?

隨着測試在 iOS 世界中成爲一種更加突出和重要的實踐,在編寫測試時瞭解自己在做什麼很重要。您的測試代碼與您的應用程序代碼一樣重要。此問題衡量您對用於輔助單元測試的對象的測試術語的理解。

預期答案:

不同的人有多種調用和分類測試對象的方式,但最常見的測試對象可以按以下方式分類:mocks、stubs和fakes。

Fakes是任何類型的 mock、fake、stub、double 等的通用總稱。就其本身而言,它們通常沒有實現,僅滿足它們所替代的類型的接口 API 要求。

stubs是假的,它做了一些有意義的工作,這些工作是測試中涉及的對象運行所必需的,但除此之外沒有其他用途。它們不能代替真實的生產對象,但可以返回存根值。他們不能斷言。

mocks是可以判定真假。Mocks 被用來代替其他對象,就像假的一樣,但它們本身記錄了一些數據,例如方法調用的數量或傳遞給測試的變量數量,以便稍後進行斷言。

注意點:

許多開發人員錯誤地將任何測試對象稱爲mocks,但是測試對象有一個特定的不同命名法,指示每個測試對象的目的。作爲一名高級開發人員,您不僅要編寫測試,還應該知道如何維護它們以及您的應用程序代碼庫。

這個問題的進一步閱讀:

20.您是否進行Code review或者Pair programming?

儘管有很多應用程序是由單獨的開發人員構建的,但應用程序的複雜性不斷增加,需要一個開發人員團隊來開發。在團隊中工作在代碼維護、協作和知識共享方面帶來了不同的挑戰。

預期答案:

Pair programming是一種實踐,其中兩個開發人員在同一臺機器上一起處理相同的任務(希望不要共享相同的屏幕和鍵盤並擁有兩套自己的)。目標是在生成代碼的地方促進協作、討論、代碼審查和 QA。這個過程使知識轉移和架構討論成爲日常事務,防止人們孤立併成爲代碼特定部分的“專家”(當那個人離開或生病時會發生什麼?)。它還提高了代碼質量,因爲在編寫代碼時,有兩組眼睛在查看代碼。這個過程同時發生在兩個開發者身上,有時被稱爲同步。

結對編程並不適合所有人,如果人們的個性不匹配,則可能是一個令人筋疲力盡的過程。儘管如此,它仍然是軟件開發中最有效的協作技術之一。

Code review是一個類似的協作和知識轉移過程,但與結對編程不同,它不會同時發生,因此是異步的。通過代碼審查,在開發人員編寫一段代碼或功能後,團隊中的其他人會查看它。審閱者檢查代碼是否有意義並建議進行更改和重構以改進它。這開啓了關於代碼的在線或離線討論,這很棒。這會將有關該代碼段的知識傳遞給其他團隊成員,並有助於儘早發現錯誤和設計異味。

代碼審查是一種參與較少的協作類型,它實現的結果與結對編程的結果大致相同。這也是一種同理心的練習,您可以向他人提供有關他們工作的反饋。

這個問題的進一步閱讀:

21.什麼是 FRP(Functional Reactive Programming)及其在 iOS 平臺中的地位?

函數式反應式編程 (FRP) 是 iOS/Swift、JavaScript 和其他開發社區的新熱點。除了它實際上不是那麼新。期待這個關於 Swift 特性的問題,或者作爲一個更大的架構和概念討論問題。

預期答案:

函數式反應式編程 (FRP) 是一種聲明式編程範式,它結合了函數式編程和反應式(異步數據流編程)範式。它是一種聲明式編程風格,您可以在其中聲明您的代碼做什麼,而不是說明它是如何做的。FRP 的反應式組件允許我們引入和描述時間的概念,這在純函數式編程中很難使用。FRP 幫助我們處理用戶輸入和 iOS 應用程序的一般異步特性;用戶輸入發生在某個時間點,網絡將在未來某個時間完成,等等。

FP 和 FRP 依賴於 map、reduce 和 filter 等高階函數,它們以函數爲參數並返回其他函數,這使得它們具有高度的可組合性。

Swift 沒有對 FRP 的原生支持,但是有兩個優秀的庫實現了函數式響應式編程概念並使我們可以輕鬆使用它們:ReactiveCocoa 和 RxSwift。

在 iOS 13 中,Apple 還宣佈了一個內置於 iOS 中的新 FRP 框架,名爲 Combine。Combine 實際上是一個類似於 RxSwift 的 FRP 框架實現。它有兩個優點:它與 SwiftUI 集成,允許將 UI 元素綁定到數據更改,並且它是 Apple 內置和支持的。缺點是:它不如 RxSwift 成熟,而且 Apple 對其進行更改和添加的速度會很慢。

注意點:

FRP 在 iOS 應用程序中變得越來越普遍,並且隨着 Apple 對這種編程範式的官方支持和 Combine 的支持,FRP 將被更多地使用。iOS 開發人員應該開始接受它。

這個問題的進一步閱讀:

22.你知道哪些 iOS 架構有這麼大的規模?

這個問題可能會在面試一家擁有龐大 iOS 開發團隊的大公司時被問到。iOS 應用程序變得越來越複雜,MVC 設計模式不能很好地支持大規模應用程序架構。對於老年人、主管、架構師等來說,這是一個非常高級的問題。

預期答案:

MVC、MVVM、MVP 和類似的設計模式都很棒,而且每一種都是彼此的改進,但對於超過 10 或 20 人的團隊,它們仍然不能很好地擴展。如果您超出了該團隊規模,則需要使用更通用和可擴展的架構方法。有這樣一種概念方法,稱爲清潔架構。

Clean Architecture 是一個概念性的規模應用架構,可以簡單地描述爲“洋蔥分層架構”。主要思想是使依賴項向內指向域邏輯和域模型,並保持其他所有內容可插入和可選(存儲數據、呈現 ui、接收或發送網絡請求的方式等)。對於 100 多名開發人員的大型團隊,這種架構的擴展性特別好。

在 iOS 上有兩個具體的 Clean Architecture 實現:VIPER 和 RIBs。

毒蛇代表視圖、交互器、演示者、實體和路由器。這些是該架構的構建塊。在這種架構中,一切都以路由器開始,以視圖結束。每個 VIPER 堆棧(意味着一組視圖、交互器、展示器、實體和路由器)是應用程序的一個屏幕或一個邏輯 UI 部分。要導航和使用 VIPER 堆棧,您需要實例化它的路由器,然後要求它創建它的視圖控制器。路由器創建一個視圖控制器、一個相應的表示器,用於爲視圖格式化數據並接收視圖的用戶輸入,一個包含業務邏輯並與演示器通信的交互器,以及交互器工作所需的實體。然後VC擁有Presenter,Presenter擁有interactor,interactor擁有實體和路由器。生成的視圖控制器在您的視圖層次結構中使用,並根據需要插入、推送或呈現。由於您的應用程序的每個部分現在都是一個 VIPER 堆棧,因此該架構允許針對團隊規模進行強大的邏輯封裝和可擴展性。

RIBs代表路由器、交互器、構建器。RIBs 是 Clean Architecture 的另一種實現,它是對 VIPER 的改進。在 RIB 體系結構中,主要構建塊是一個 RIB,一組一個路由器、一個交互器和一個帶有可選視圖和展示器的構建器。沒有視圖的 RIB 稱爲無頭 RIB。就像在 VIPER 架構中一樣,您使用路由器從一個 RIB 路由到另一個 RIB,並將您的應用程序的整個運行時構建爲具有父級和子級 RIB 的樹結構。由於視圖是可選的,與 VIPER 不同,您的應用程序樹結構可能會也可能不會模仿您的視圖層次結構。

Builder 負責爲交互器、路由器以及組裝和初始化它們的視圖/展示器獲取或創建依賴項。

路由器負責導航到特定的子 RIB。

Interactor 負責所有業務邏輯並使用路由器啓動路由。

Presenter 和視圖通常組合在一個視圖控制器中,其中 Presenter 負責對數據進行按摩和格式化以在視圖中顯示。

View負責在屏幕上顯示數據並收集用戶輸入。

這個問題的進一步閱讀:

結論

這篇文章中涵蓋的問題涉及 iOS 開發人員應該瞭解的廣泛主題。這絕不是一個全面的清單。這些問題基於《iOS 面試指南》一書所做的研究。

如果你正在跳槽或者正準備跳槽不妨動動小手,添加一下咱們的交流羣1012951431來獲取一份詳細的大廠面試資料爲你的跳槽多添一份保障。

文末推薦:iOS熱門文集

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章