我遇到了 SwiftUI 状态的架构问题。
考虑具有单向数据流的架构。
class Store: ObservableObject {
@Published private(set) var state: AppState = AppState(initialValue: 0)
func fetchInitialValue() async {
try? await Task.sleep(for: .seconds(1))
state = AppState(initialValue: 5)
}
}
struct AppState {
let initialValue: Int
}
我们有一个
ObservableObject
- Store
,它有一个@Published
变量State
,只能在内部更新。此状态包含某个视图的初始值,可以在视图最初呈现后更新(例如,它可以从某个远程系统获取)。
现在,这个
initialValue
应该只是那个视图的初始值,它不应该是双向绑定,但是无论何时更新,视图都应该更新。
这是使用此状态的示例视图层次结构。请注意,视图可以自行更改值,这不应该影响
initialValue
.
struct MainView: View {
@ObservedObject var store = Store()
var body: some View {
VStack {
Text("Initial value is \(store.state.initialValue)")
SubView(initialValue: store.state.initialValue)
}
.onAppear {
Task {
await store.fetchInitialValue()
}
}
}
}
struct SubView: View {
@State var currentValue: Int
init(initialValue: Int) {
currentValue = initialValue
}
var body: some View {
VStack {
Stepper(value: $currentValue) {
Text("Current value is \(currentValue)")
}
}
}
}
问题是
SubView
不会在状态更新时更新,因为它的子视图都不依赖于 initialValue
.
任何想法如何强制
SubView
重新创建状态变化?
View 重新呈现状态更改。传递像
initialValue
这样的整数值类型不会根据商店更新它。所以让它改变状态。例如使用 id
修饰符:
SubView(initialValue: store.state.initialValue)
.id(store.state.initialValue)
或经过商店本身:
SubView(store: store)