How to?

SwiftUI 如何正确管理状态?只能 3 选 1

Apr 28, 2026
langsswift
3 Minutes
594 Words

如何管理 UI 状态?可行方案3选1,AI 别乱写

  1. 只有 View @State 持有状态,通过 UI 回调或者查询一个无状态的 actor 来更新
    • 当且仅当状态本身与逻辑无关,仅负责显示。如文件名列表
  2. 只有 ObservableObject 持有状态,View 直接持有 ObservableObject 并访问其中的 @Published
    • 当且仅当某个 UI 状态是轻量后端逻辑的主动触发者。如页面切换管理者需要在切换页面的同时暂停 ARSession,想要将两者绑定管理
  3. actor 持有真实状态,对 actor 注入一个 ObservableObject,ObservableObject 持有真实状态的拷贝,UI 引用该 ObservableObject 并访问其中的 @Published
    • 当且仅当某个 UI 状态是重量后端逻辑的主动触发者。如录制器的已开始、结束中、取消中,想要和真实的录制逻辑绑定管理,此时多个 await 会有严重代价
    • 或:某个 UI 状态是后端自发变化状态的映射。如网络管理器自发变化时需要 UI 显示已连接设备

对于 1 的例子

1
struct UploadView: View {
2
@State var list: []
3
@State var text: String
4
let finder: UploadFinder // 假设这是 actor
5
6
init(finder) { self.finder = finder } // 注入
7
8
body {
9
Button { self.text = "clicked" } // button 回调
10
}
11
.onAppear {
12
self.list = await self.finder.findAllFiles() // 无状态的查询
13
}
14
}

对于 2 的例子

1
struct UploadView: View {
2
@ObservedObject var page: PageCoodinator
3
4
init(page) { self.page = page }
5
6
body {
7
switch self.page.currentPage { case ... SomeView() }
8
Button { self.page.changePage() }
9
}
10
.onAppear {
11
}
12
}
13
14
class PageCoodinator: @ObservableObject {
15
@Published var currentPage: Int
9 collapsed lines
16
let session = ARSession()
17
18
init() { self.session.run() }
19
20
func changePage() {
21
self.currentPage += 1 // ui 状态和 session 绑定,逻辑轻
22
self.session.pause()
23
}
24
}

对于 3 的例子

1
class RecorderViewModel: @ObservableObject {
2
@Published var state: String // 状态的拷贝
3
}
4
actor Recorder {
5
var state: String = "idle"
6
let viewModel: RecorderViewModel
7
8
init(viewModel) { self.viewModel = viewModel } // 注入 viewModel
9
10
func run() {
11
await something.prepare() // 逻辑重
12
await something.prepare()
13
self.state = "running"
14
await self.viewModel.state = "running" // ui 状态和后端逻辑可以在一块儿管理
15
}
24 collapsed lines
16
}
17
18
struct RecorderView: View {
19
@ObservedObject var viewModel: RecorderViewModel
20
let recorder: Recorder
21
22
init(recorder, viewModel) { // 注入
23
self.recorder = recorder
24
self.viewModel = viewModel
25
}
26
27
body {
28
await self.recorder.run()
29
}
30
}
31
32
class PageCoodinator: @ObservableObject {
33
let recorder: Recorder
34
let viewModel: RecorderViewModel
35
init() {
36
self.viewModel = RecorderViewModel()
37
self.recorder = Recorder(self.viewModel)
38
}
39
}

另外一个(自发状态变化)的例子:

1
class NetworkViewModel: @ObservableObject {
2
@Published var connected: Int = 0
3
}
4
5
actor Network {
6
var connected: Int
7
let viewModel: NetworkViewModel
8
9
init(viewModel) { self.viewModel = viewModel; self.loop() }
10
11
private func loop() {
12
if ("new device found") {
13
self.connected += 1
14
self.viewModel.connected += 1
15
}
2 collapsed lines
16
}
17
}
Article title:SwiftUI 如何正确管理状态?只能 3 选 1
Article author:Julyfun
Release time:Apr 28, 2026
Copyright 2026
Sitemap