一、Swift 內(nèi)存 & 值語義(★★★★★)
Q21:struct 和 class 本質(zhì)區(qū)別?
struct 是 值類型,存儲(chǔ)在?;?inline storage 中,賦值時(shí)發(fā)生 copy。
class 是 引用類型,存儲(chǔ)在堆上,變量保存的是指針。
核心區(qū)別:
struct → 值語義
class → 引用語義
? 值語義帶來線程安全
? 避免共享狀態(tài)
Swift 優(yōu)先推薦 struct 是為了 predictable state。
Q22:什么是 Copy-on-Write(COW)?
Copy-on-Write 是一種 延遲復(fù)制優(yōu)化:
- 多個(gè)變量共享同一內(nèi)存
- 當(dāng)發(fā)生寫操作時(shí)才真正復(fù)制
var a = [1,2,3]
var b = a // 未復(fù)制
b.append(4) // 此時(shí)復(fù)制
通過 isKnownUniquelyReferenced 判斷引用唯一性。
為什么 Swift Array 性能高?
因?yàn)?COW 避免不必要復(fù)制。
Q23:struct 一定在棧上嗎?
struct 不一定在棧上,它的存儲(chǔ)位置由編譯器決定,可能在棧、堆甚至寄存器中。比如作為局部變量時(shí)通常在棧上,但如果作為 class 的成員或者被閉包捕獲,可能會(huì)分配在堆上。本質(zhì)上,struct 的核心是值語義,而不是具體的內(nèi)存位置,這一點(diǎn)和 class 的引用語義是本質(zhì)區(qū)別
Q24:mutating 關(guān)鍵字作用?
因?yàn)?struct 是值類型。
mutating 表示:方法內(nèi)部允許修改 self。
本質(zhì):
self = newSelf
二、Swift Dispatch 機(jī)制(?? 高頻殺手)
| 類型 | dispatch |
|---|---|
| class override | dynamic |
| protocol extension | static |
| final | static |
| generic | static |
Q26:protocol extension 為什么可能不走重寫?
protocol extension 默認(rèn)是 static dispatch。
只有 protocol requirement 才是 dynamic dispatch。
protocol A {
func test()
}
extension A {
func test() { print("A") }
}
調(diào)用取決于類型聲明方式。
Swift 優(yōu)先靜態(tài)派發(fā)提升性能。
三、Closure(★★★★★)
Q27:closure 捕獲變量還是值?
捕獲的是變量引用(capture by reference)。
var a = 10
let c = { print(a) }
a = 20
c() // 20
Q28:[weak self] 原理?
closure 捕獲:
weak reference -> side table
避免 closure strong 持有 self。
capture list 在 closure 創(chuàng)建時(shí)執(zhí)行。
Q29:escaping closure 是什么?
closure 生命周期逃離當(dāng)前函數(shù)作用域。
例如:
- 網(wǎng)絡(luò)回調(diào)
- async 執(zhí)行
為什么需要標(biāo)記?
因?yàn)椋?br>
編譯器需要改變內(nèi)存管理策略。
四、泛型(8 年高頻)
Q30:泛型優(yōu)勢(shì)?
- 代碼復(fù)用
- 類型安全
- 編譯期檢查
- 無 runtime casting
Q31:associatedtype 是什么?
用于 protocol 中定義占位類型。
protocol Container {
associatedtype Item
}
Q32:為什么不能直接用帶 associatedtype 的 protocol?
因?yàn)椋?br>
編譯器無法確定具體類型大小。
所以需要:
?? Type Erasure
Q33:什么是 Type Erasure?
把具體泛型類型隱藏為統(tǒng)一類型。
AnySequence
AnyPublisher
核心思想:
用 box 包裝真實(shí)類型。
一句話:
抹去泛型信息以統(tǒng)一接口。
五、Swift Concurrency(現(xiàn)在面試必問)
Q34:async/await 解決什么問題?
- callback hell
- 可讀性差
- 錯(cuò)誤傳播困難
- 讓異步代碼像同步代碼。
Q35:async/await 本質(zhì)是多線程嗎?
是協(xié)程(cooperative concurrency)。
任務(wù)可掛起,不阻塞線程。
Q36:Task 是什么?
Task 是 Swift 并發(fā)的基本執(zhí)行單元。
類似輕量級(jí)協(xié)程。
Q37:Task 和 GCD 區(qū)別?
| Task | GCD |
|---|---|
| 結(jié)構(gòu)化并發(fā) | 手動(dòng)管理 |
| 自動(dòng)取消傳播 | 無 |
| async/await | callback |
Q38:什么是 Structured Concurrency?
子任務(wù)生命周期綁定父任務(wù)。
父取消 → 子全部取消。
Q39:Actor 為什么線程安全?
Actor 內(nèi)部狀態(tài)一次只允許一個(gè)任務(wù)訪問。
actor mailbox queue
串行執(zhí)行。
一句總結(jié):
Actor = async + serial queue + state isolation
Q40:MainActor 作用?
保證代碼運(yùn)行在主線程。
@MainActor
class ViewModel {}