SwiftUI TextField 在变量更改时不刷新
SwiftUI TextField not Refreshing on Variable Change
我在 List
内有 TextField
在 NavigationView
内,声明如下:
NavigationView {
List {
Section("Item Name") {
TextField("", text: $itemName)
.textInputAutocapitalization(.sentences)
.disableAutocorrection(false)
.textFieldStyle(.plain)
}
}
}
在 NavigationView
的 .onAppear
方法中,我设置了用 @State
声明的文本字段的文本变量,如下所示:
@State var itemName: String = ""
和:
.onAppear {
itemName = "Hello, World!"
}
文本设置正确,但文本字段不刷新。我知道是因为我可以访问文本字段的文本 属性 并获取更新后的值,当用户点击文本字段进行编辑时,文本突然出现。
在我看来,变量更改时文本字段更新其视图是个问题。我是否必须调用与 UIKit 的 layoutSubviews
等效的 SwiftUI?还是我声明我的 itemName
变量错误?
最小可重现示例 (MRE):
struct ItemView: View {
@State var itemName: String = ""
var body: some View {
NavigationView {
List {
Section("Item Name") {
TextField("", text: $itemName)
.textInputAutocapitalization(.sentences)
.disableAutocorrection(false)
.textFieldStyle(.plain)
}
}
.navigationTitle("Item")
}
.onAppear {
itemName = "Hello, World!"
}
}
}
如有任何帮助,我们将不胜感激。
它在预览中运行良好,但我进行了下一步并在模拟器中对其进行了测试,但它失败了。这使我意识到问题所在。我们在从 .onAppear()
开始的动画中看到了很多这种情况。在视图实际显示在屏幕上之前设置视图并调用 .onAppear()
,导致无法从 .onAppear()
更新。几乎可以将其视为竞争条件。在调用更新之前必须设置视图并显示在屏幕上,并且需要额外的周期来执行此操作。因此修复很简单:
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now()){
itemName = "Hello, World!"
}
}
将其包裹在 DispatchQueue.main.asyncAfter(deadline:)
中。这给了它时间来避免这个问题。
我也能够重现它。我同意 Yrb,似乎 onAppear 中的状态突变发生在 TextField
的更新期间,因此文本字段没有从状态中获取新值。
我能够修复它的另一种方法是将状态突变从 NavigationView
的 .onAppear
修饰符移动到 TextField
的 .onAppear
修饰符。如果这样做,就不需要 DispatchQueue.main.async
因为 SwiftUI 会正确同步 onAppear 块的执行与文本字段的更新。
我在 List
内有 TextField
在 NavigationView
内,声明如下:
NavigationView {
List {
Section("Item Name") {
TextField("", text: $itemName)
.textInputAutocapitalization(.sentences)
.disableAutocorrection(false)
.textFieldStyle(.plain)
}
}
}
在 NavigationView
的 .onAppear
方法中,我设置了用 @State
声明的文本字段的文本变量,如下所示:
@State var itemName: String = ""
和:
.onAppear {
itemName = "Hello, World!"
}
文本设置正确,但文本字段不刷新。我知道是因为我可以访问文本字段的文本 属性 并获取更新后的值,当用户点击文本字段进行编辑时,文本突然出现。
在我看来,变量更改时文本字段更新其视图是个问题。我是否必须调用与 UIKit 的 layoutSubviews
等效的 SwiftUI?还是我声明我的 itemName
变量错误?
最小可重现示例 (MRE):
struct ItemView: View {
@State var itemName: String = ""
var body: some View {
NavigationView {
List {
Section("Item Name") {
TextField("", text: $itemName)
.textInputAutocapitalization(.sentences)
.disableAutocorrection(false)
.textFieldStyle(.plain)
}
}
.navigationTitle("Item")
}
.onAppear {
itemName = "Hello, World!"
}
}
}
如有任何帮助,我们将不胜感激。
它在预览中运行良好,但我进行了下一步并在模拟器中对其进行了测试,但它失败了。这使我意识到问题所在。我们在从 .onAppear()
开始的动画中看到了很多这种情况。在视图实际显示在屏幕上之前设置视图并调用 .onAppear()
,导致无法从 .onAppear()
更新。几乎可以将其视为竞争条件。在调用更新之前必须设置视图并显示在屏幕上,并且需要额外的周期来执行此操作。因此修复很简单:
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now()){
itemName = "Hello, World!"
}
}
将其包裹在 DispatchQueue.main.asyncAfter(deadline:)
中。这给了它时间来避免这个问题。
我也能够重现它。我同意 Yrb,似乎 onAppear 中的状态突变发生在 TextField
的更新期间,因此文本字段没有从状态中获取新值。
我能够修复它的另一种方法是将状态突变从 NavigationView
的 .onAppear
修饰符移动到 TextField
的 .onAppear
修饰符。如果这样做,就不需要 DispatchQueue.main.async
因为 SwiftUI 会正确同步 onAppear 块的执行与文本字段的更新。