@State、@Binding、@ObservedObject 到底差在哪?SwiftUI 的 State System 真正設計思想
很多 iOS 工程師在學 SwiftUI 時,最常問的是:
@State、@Binding、@ObservedObject、@StateObject 到底怎麼分?
然後開始背:
- @State 給自己用
- @Binding 給子 View
- @ObservedObject 給外部 object
- @StateObject 負責生命週期
背完之後,畫面可能能跑。
但只要專案開始變大,很快就會出現:
- state 不同步
- UI 不更新
- object 被重建
- ViewModel 消失
- 畫面亂刷新
- lifecycle 混亂
因為 SwiftUI 真正困難的地方,從來不是 syntax。
而是:
你是否理解「State Ownership」
1. SwiftUI 的本質:View 是 State 的投影
UIKit 時代:
你操作 View
SwiftUI 時代:
你改變 State
View 只是:
State 的結果(projection)
例如:
struct CounterView: View {
@State private var count = 0
var body: some View {
Text("\(count)")
}
}
真正重要的不是:
Text()
而是:
count
因為:
SwiftUI 是 state-driven UI framework
2. SwiftUI 最大誤解:View 不是真正的畫面
這是 SwiftUI 最反直覺的地方。
很多人以為:
struct MyView: View
是一個畫面 instance。
其實不是。
SwiftUI View 本質上更像:
State Description
甚至可以理解成:
UI Function
例如:
var body: some View {
Text("\(count)")
}
其實很接近:
UI = f(state)
這也是為什麼:
View 可以被瘋狂重建
因為真正重要的不是 View。
而是:
State 是否被保存
3. @State 真正代表的是「Local Ownership」
很多人背:
@State 是 local state
但這不夠準確。
真正意思是:
這份 state 的 ownership 屬於這個 View
例如:
struct CounterView: View {
@State private var count = 0
var body: some View {
Button("\(count)") {
count += 1
}
}
}
重點不是:
count 可以改
而是:
SwiftUI 幫你保存 state lifecycle
即使 View 被重新建立:
State 仍然存在
4. 為什麼普通 var 不能更新 UI?
例如:
struct CounterView: View {
var count = 0
var body: some View {
Text("\(count)")
}
}
因為:
SwiftUI 不追蹤普通 property
只有被 State System 管理的資料:
- @State
- @Binding
- @ObservedObject
- @EnvironmentObject
才會觸發:
View invalidation
5. @Binding 真正的本質:Temporary Ownership Transfer
很多人背:
@Binding 是雙向綁定
但真正更準確的是:
Ownership 沒有改變,只是暫時借你修改權限
例如:
struct ParentView: View {
@State private var isOn = false
var body: some View {
ChildView(isOn: $isOn)
}
}
子 View:
struct ChildView: View {
@Binding var isOn: Bool
}
重點是:
真正擁有 state 的仍然是 ParentView
Child 只是:
獲得修改權限
這其實非常像:
reference to value ownership
6. @ObservedObject 最大問題:Ownership 不明確
這是很多 SwiftUI bug 的來源。
例如:
struct ContentView: View {
@ObservedObject var vm = ViewModel()
}
很多人以為沒問題。
但其實:
View 重建時 vm 可能也被重建
因為:
ObservedObject 不負責 lifecycle
它只是:
觀察外部 object
7. @StateObject 為什麼會出現?
因為 Apple 發現:
大家都在亂管理 object lifecycle
所以:
@StateObject private var vm = ViewModel()
真正意思是:
這個 View 擁有 ViewModel 的生命週期
這很重要。
因為 SwiftUI 真正困難的從來不是畫 UI。
而是:
誰擁有 state
8. SwiftUI 最大核心:Single Source of Truth
這是 SwiftUI 幾乎所有設計的核心。
問題永遠是:
這份 state 到底誰說了算?
如果:
- Parent 一份 state
- Child 一份 state
- ViewModel 又一份 state
最後就會:
state divergence
也就是:
資料不同步
所以 SwiftUI 一直強調:
Single Source of Truth
9. 為什麼 TCA 幾乎是 SwiftUI 的終極延伸?
因為 SwiftUI 雖然有 State System。
但:
大型專案 state 還是容易失控
所以 TCA 開始進一步強制:
- 單向資料流
- centralized state
- predictable mutation
- effect isolation
本質上:
TCA 是把 SwiftUI 的 State Thinking 推到極致
10. SwiftUI 真正困難的是「State Explosion」
小專案:
SwiftUI 很快樂
大專案:
state 開始爆炸
例如:
- loading state
- navigation state
- sheet state
- async state
- cache state
- error state
最後:
整個畫面都在同步 state
這也是為什麼:
State Management 會變成架構問題
不是 UI 問題。
11. 面試真正想考的是什麼?
這類題目真正考的不是:
你會不會用 property wrapper
而是:
- 你是否理解 ownership
- 你知不知道 lifecycle
- 你能不能管理 state flow
- 你會不會避免 duplicated state
- 你能不能設計 predictable UI
真正成熟的工程師,不會只背:
@State 給自己用
而是會知道:
每個 property wrapper 都代表不同的 state ownership model
結論
SwiftUI 的核心從來不是:
Declarative UI
真正的核心其實是:
State Ownership System
而:
- @State
- @Binding
- @ObservedObject
- @StateObject
本質上都在回答同一件事:
這份 state 到底誰擁有?
延伸思考
當你開始深入:
- TCA
- Actor
- Async State
- Reducer Architecture
- Unidirectional Data Flow
你會發現:
SwiftUI 真正想推動的方向其實是:
讓 UI 不再直接操作畫面,而是操作 state。
因為:
畫面本身不難管理
真正難管理的是 state。










