我們稱 Alamofire 為函式庫,稱 SwiftUI 為框架。但兩者不都是「拿來使用別人寫的程式碼」嗎?到底有什麼不同?
大家常聽到的答案是「框架比較大」,但大小不是本質。小型框架和巨型函式庫都存在。
誰呼叫誰。
掌握這唯一的判準後,就能自然連結到控制反轉(IoC)這個重要概念。學習相依性注入時也會再次遇到它,所以在這裡打好基礎很有幫助。
以下是重點總結。
- 函式庫:我的程式碼在需要時呼叫的工具集合。控制權在我手上
- 框架:掌握流程並呼叫我的程式碼的骨架。控制權在框架手上
- 這種顛倒的呼叫方向稱為控制反轉
- 好萊塢原則:「別打電話給我們,我們會聯絡你」
函式庫:由我呼叫的工具
函式庫是一組事先實作特定功能的程式碼。何時使用、以什麼順序使用,完全由我的程式碼決定。
// 流程的主導權在我的程式碼
let json = try JSONDecoder().decode(User.self, from: data)
let hash = SHA256.hash(data: input)
程式的開始、結束與整體流程由我規劃,再在中途取用需要的工具。這就像從工具箱拿出螺絲起子使用;螺絲起子不會決定工作的順序。
Alamofire、Kingfisher 都屬於這一類。何時送出網路要求、何時載入圖片,由我決定。
框架:呼叫我的骨架
框架是預先建立應用程式整體結構與執行流程的骨架。我只要把程式碼填入骨架留下的空位。
以 iOS App 為例就很清楚。App 的起點、事件迴圈與畫面生命週期,全都由 UIKit、SwiftUI 掌握。我撰寫的 viewDidLoad、body、onAppear 等,是框架在指定時機呼叫的程式碼。
struct ProfileView: View {
var body: some View { // 不是由我呼叫.
Text("Hello") // SwiftUI在需要時呼叫
}
}
我們不會親手呼叫 body。何時呼叫、呼叫幾次由 SwiftUI 決定。流程的主導權已經對調。
控制反轉,以及好萊塢原則
這種顛倒的關係有它的名稱:控制反轉(IoC)。
在一般程序式程式中,我的程式碼掌握控制流程並呼叫外部程式碼。在以框架為基礎的程式中,框架掌握流程,而我的程式碼會在註冊的位置被呼叫。控制權轉向相反方向,因此稱為「反轉」。
用風趣方式表達這件事的說法,就是好萊塢原則。
「別打電話給我們,我們會聯絡你。」— 別打電話來,我們會聯絡你。
參加試鏡的演員不會一直打電話給製作公司,而是獲選後由製作公司聯絡。框架與我的程式碼之間,正是這種關係。
代理模式也是相同的原理。實作 UITableViewDataSource 時,是我呼叫 cellForRowAt 嗎?不是。表格視圖有需要時會呼叫我。框架世界的語法已滲入程式碼的各個角落。
所以在實務上有什麼不同?
學習方式不同。函式庫只要找出「有哪些功能」即可,但框架必須先了解「何時會呼叫我」(生命週期與呼叫規約)。這就是學習 UIKit 要從生命週期開始的原因。
替換成本不同。函式庫只要修改呼叫處就能替換,但整份程式碼都建立在框架骨架上,因此替換實際上等於重寫。UIKit → SwiftUI 的轉換不是修改幾個函式就能完成,也正是這個原因。
測試策略不同。框架呼叫的程式碼很難脫離框架單獨執行。因此才會反覆建議將邏輯分離到不依賴框架的層(純 Swift)。
面試時用一句話說明
「函式庫是由我的程式碼呼叫的工具,而框架是掌握控制流程並呼叫我的程式碼的骨架。這種控制權方向的差異,稱為控制反轉。」
追問通常會依序是「請舉一個 IoC 的例子」(生命週期方法、代理),以及「這樣有什麼好處」(標準化流程,讓開發者專注於商業邏輯)。
總結
- 區分標準不是大小,而是呼叫方向
- 函式庫:我的程式碼在需要時呼叫的工具。控制權在我手上
- 框架:掌握流程並在指定時機呼叫我的程式碼的骨架。控制權在框架手上
- 這種顛倒的控制權就是控制反轉(IoC),別名是好萊塢原則
- viewDidLoad、body、代理方法全都是「被呼叫」的程式碼
- 實務差異:先學框架生命週期、替換困難,而分離邏輯是測試的核心

