【发布时间】:2021-09-23 03:45:17
【问题描述】:
我遇到了一个奇怪的问题,即 @State var 没有更新 iOS SwiftUI 视图。 我有一个带有游戏主题列表的 NavigationView 的小型游戏主题的编辑屏幕。当处于编辑模式并选择其中一个主题时,我会打开一个编辑器视图,将主题作为绑定传递给编辑器视图结构。 在我的编辑器视图中,我有部分允许用户编辑主题的属性。我不想在我的编辑字段中使用对各种主题属性的绑定,因为我不希望更改立即生效。相反,我为这些属性中的每一个创建了@State 变量,然后在编辑字段中使用这些属性的绑定。这样,我让用户可以选择取消而不使更改生效,或者选择“完成”以通过绑定将更改分配回主题。 为了初始化 @State vars,我有一个 onAppear 块,它从各自的主题属性中分配 @State vars 值。 我遇到的问题是,当执行 onAppear 块并分配变量时,相关的编辑字段没有更新! 这是我的代码的精简版:
struct EditorView: View {
/// The current presentation mode of the view.
@Environment(\.presentationMode) var presentationMode
@Binding var theme: GameTheme
@State private var name = ""
...
var body: some View {
NavigationView {
Form {
nameSection
...
}
.navigationTitle("Edit \(theme.name)")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel", action: cancel)
}
ToolbarItem(placement: .confirmationAction) {
Button("Done", action: saveTheme)
.disabled(!canSaveTheme)
}
}
.onAppear {
name = theme.name
...
}
}
.frame(minWidth: Constants.minViewSize.width, minHeight: Constants.minViewSize.height)
}
var nameSection: some View {
Section(header: Text("Name")) {
TextField(LocalizedStringKey("Name"), text: $name)
}
}
...
}
所以视图会在出现时显示,@State var 名称确实从 theme.name 中正确分配了值;但是,此分配不会导致视图更新,并且“名称”的值不会输入到 TextField 中。
有趣的是,我不知道这是不是一件好事,如果我将 onAppear 块的内容包装在 DispatchQueue.main.async 中,一切正常!
即
.onAppear {
DispatchQueue.main.async {
name = theme.name
...
}
}
有没有人知道如何在 onAppear 中强制刷新视图?或者,为什么对“name”的赋值不强制更新?
谢谢。
【问题讨论】:
-
您应该将绑定变量传递给 init 而不是 onAppear。然后你可以使用绑定变量来设置@State变量。
-
因为您要更改
class GameTheme中的变量。@State观察整个对象。这意味着它只会在它是struct或类似String的情况下发生变化。如果要观察class的变量,则必须使其符合ObservableObject并用@Published包装变量,然后使用@StateObject或@ObservedObjec -
我似乎已经用 init() 解决了我的问题。我创建了
init(theme: Binding<GameTheme>),然后在init中通过_theme = theme分配了主题,然后通过_name = State(initialValue: theme.name.wrappedValue)分配了名称。