面試攻略:2023 年 iOS 語言特性問題集錦

Reed Hsin
8 min readFeb 11, 2024

--

我整理了通常在第一、二關,會被問到了一些關於 Swift 和 Objc 程式語言特性的問題,總共有 12 道題目,一些太冷門的我就不放上來了🥶

我把這些問題分成了四大類,每個類別裡的問題都互有關聯

第一類: Objc 與 Swift 的差異比較

第二類: 何謂 Dynamic Dispatch 和 Static Dispatch

第三類:Swift 中的 class 和 struct 的比較

第四類:你對 inout 和 mutatuing 關鍵字的理解

基本上,不管面試官問到哪一大類裡面的某個問題,若你想回答得更全面的話,都可以直接參考我的回答

以下都是基於我在面試過程中的實際回答,並與其他同事討論後的所整理出來的結果 🙌

Objc 和 Swift 的差異

動態語言和靜態語言的差異

為什麼會說 Swift 在 runtime 時的運行效率會較 Objc 還高

我會先從動態語言和靜態語言切入,並解釋兩者的差異

兩者差異在於它們怎麼處理數據類型和什麼時候檢查這些類型

動態語言像是 Objective-C,在 compile 階段不會做變量的類型檢查和判斷,這讓開發非常靈活,因為可以在 runtime 才決定變量類型

但這樣的代價,就是可能降低 runtime 時效率

因為得時刻檢查類型,還會有因為類型錯誤導致 crash 的風險

靜態語言如 Swift,在 compile 時就檢查好類型,雖然 compile time 可能較久,但 runtime 時的效率會高出許多,因為省去了檢查類型的時間

靜態語言通常更穩定,因為類型一旦確定,且無法在 runtime 時更改類型,所以不會發生因為類型錯誤而導致的 crash

最後我會再強調 Objc 的動態特性,比如動態方法解析(Dynamic Method Resolution)、消息轉發(Message Forwarding),還有方法交換(Method Swizzling)…等。

而 Swift 則是更好地支援了 functional programming,像是用 map、reduce 這些函數來處理數據

並把很多基本數據類型和資料結構都設計成 Value Type,意味著在記憶體中,對 stack 的指針操作會較 refernce type 對 heap 的鏈結操作更為高效

並加上 copy-on-write 技術,讓 Swift 在許多場合下都會比 Objc 更有效率

解釋何謂 dynamic dispatch 和 static dispatch

說明 final 關鍵字的功能

Objc 有哪些方式可以做到 static dispatch

Swift有哪些方式可以做到 dynamic dispatch

這邊我會先解釋靜態派發和動態派發的區別

動態派發會直到 runtime 時,才由系統去找出真正要調用的 method implementation

予開發者極高的靈活性,但也因為增加了查找 method implementation 的額外開銷,使得效率降低

靜態派發則是在 compile 階段便決定了之後要調用的 method 的 implementation

同時 compiler 也會在 compile 階段進行 inline 的優化

這在 runtime 時提供了系統更好的效能,因為不用有查找 method implementation 的額外開銷

Objc 主要是 Dynamic Dispatch,Swift 主要是 Static Dispatch

以下講解 Swift 在何時會是 Dynamic or Static Dispatch

Swift 針對 Value Type 以及有標記為 final 的 class methods 都會用 Static Dispatch 的方式

但若是無 final 的 class method 便會用 Dynamic Dispatch 的方式,在 runtime 時透過查找 V-Table 找到 method implementation

同時針對 protocol 以及 inherited 的 subclass 也會用 Dynamic Dispatch 的方式

且 swift 也提供了 dynamic 的 keyword,讓開發者可以選擇 Dynamic Dispatch

以下講解 Objc 何時會是 Static Dispatch

而 Objc 則是非常單純地幾乎完全依賴 Dynamic dispatch,但也可以用以下的方式達到 static dispatch 的目的

a. 直接調用 c 函數

b. 使用 inline 關鍵字,直接把函數的具體實現放到函數的調用位置

c. class function 因為沒有涉及到 instance object,所以會使用 static dispatch

8. Swift 中的 struct 和 class 的差異

9. pass by value 和 pass by reference 的差異

10. 你什麼時候會用 struct 和 class

可以先就 class 和 struct 的特性、在記憶體是怎麼去做分配的以及各自的優勢(同時也意味著其使用情境)

class 是 reference type

當宣告 class 的 instnce object 時,系統會在 memory 中的 heap 區域去做配置,也因為涉及了鏈結操作的操作,所以運行時效率較 value type 低

class 的 instance object 需要透過引用計數(reference count) 來管理其在 memory 的生命週期,這也增加了額外的記憶體管理開銷

當 class 的 instance object 被傳遞時,其實是傳遞其 reference(指向其記憶體位址的 pointer)

所以需要擔心其同步問題,以及在多線程的環境下的 thread safe issue

class 的優勢在於,可以用來繼承,且一個相同的 class 可同時在多個地方被引用,方便同步資料

struct 是 value type

當宣告 struct 的 instance object 時,系統會在 memory 中的 stack 區域去做配置,因為指示 pointer 的移動操作,所以運行時效率較 reference type 高

struct 的 instance object 無需引用計數來管理其生命週期,因為當被傳遞時,實際上會 copy 一份新的 instance object 傳遞出去,所以無需擔心其資料同步問題,從而減少記憶體管理的開銷

Copy-on-Write 的機制,確保了 struct 的 instance object 被 copy 後,並不會立即分配新的記憶體位置

而是直到新的 instance object 被修改後才會,真正的為其分配新的記憶體位置,也增加了其運行時的效率

struct 的優勢在於,因為相同的 struct 無法在多個地方被引用,所以不用擔心數據同步的問題,也不用擔心 memory leak issue,同時其運行時效能還較 class 高

11. 說明 mutating, inout 關鍵字的功能以及底層實現

12. 說明 inout 關鍵字的功能以及底層實現

先就功能與場景層面說明這兩個 keyword

透過 memory 的配置及系統所做的步驟,說明其底層實現

mutating 用於修飾可修改 value type 內部成員變量的 function

struct Point {
var x: Int
var y: Int

mutating func moveBy(x deltaX: Int, y deltaY: Int) {
x += deltaX
y += deltaY
}
}

由於 struct 是 value type,所以默認是無法修改其成員變量,但可以透過 mutating 修飾 method,讓其可以修改 value type 的內部成員變量

當調用一個 mutating 修飾的方法時更改 struct 的某個成員變量時,實際上是在修改期拷貝後的 instance object,可視為一個新的 instance object

inout 用於標記函數的參數為可修改的 reference type

func swapTwoInts(a: inout Int, b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(a: &someInt, b: &anotherInt)

默認情況下,函數所傳遞的參數是 constance,若希望可以在函數內部修改參數的值,並在函數結束時仍可保留此修改,此時就可以用 inout 來標記參數

系統會在調用函數時,為有被 inout 修飾的參數創建一個臨時的拷貝,並將此拷貝的記憶體位置傳遞給參數(pass by reference),函數內部的修改會作用在這個新的拷貝上

當函數結束後,系統會將這個臨時拷貝的狀態寫回原始傳遞進來的變數,這確保了即使變數是 value type,其修改也可以反映到函數外

以上就是我在 2023 年面試過程中遇到的,關於 Swift 和 Objective-C 語言特性的考查問題

隨著 Swift 變得越來越流行,很多關於語言特性的問題都專注於 Swift

當然,那些 Objective-C code base 仍然龐大的老牌公司來說,對 Objective-C 的語言特性的考察便會較多

但若你的準備時間有限的狀況下,建議還是先從熟悉 Swift 相關面試題下手!

在回答這類語言特性的問題時,建議先從日常應用和基礎知識入手,這樣做可以幫助你快速建立與面試官的共鳴

接著,觀察面試官對這些問題的理解深度,依此來決定是否需要深入探討更技術性或底層的細節

作為面試者,合理分配面試時間,聚焦於面試官最感興趣的議題,是非常重要的

最後希望我整理的這些資料能夠幫助大家在面試前快速回顧並掌握相關的知識點,拿到滿手喜歡的 offer 🙌 🙌 🙌

--

--

Reed Hsin

在電商、直撥串流、加密貨幣、社交媒體等領域都有豐富經驗的資深 iOS 工程師,曾在 KKBox、Pinkoi、17Live、Crypto.com,目前於 TikTok 任職。 多年來,我帶領許多非電資背景的學生轉職成為 iOS 工程師,也幫助資深 iOS 工程師轉職到外商 🙌 希望能的經驗,能讓大家在職場上閃閃發光✨