我需要建立一个文本字段列表,其中每个字段都与焦点id关联,以便在收到焦点时自动滚动到这样的文本字段.实际上,真正的应用程序要复杂一些,它还包括文本编辑器和许多其他控件.
现在,我发现如果我的视图定义了@Environment(\.dismiss) private var dismiss
,那么列表在手动滚动期间一直在重建.如果我只是注释掉第@Environment(\.dismiss) private var dismiss
行,那么当我滚动时就不会重建列表.显然,当用户单击某个按钮时,我希望能够关闭我的视图.在真正的应用程序中,情况甚至更糟:在滚动过程中,所有内容都滞后,我无法平滑滚动.我的 list 并不多,只有10个左右的项目.
下面是一个演示示例:
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink {
DismissListView()
} label: {
Text("Go to see the list")
}
}
}
}
struct DismissListView: View {
@Environment(\.dismiss) private var dismiss
enum Field: Hashable {
case line(Int)
}
@FocusState private var focus: Field?
@State private var text: String = ""
var body: some View {
ScrollViewReader { proxy in
List {
let _ = print("body is rebuilding")
Button("Dismiss me") {
dismiss()
}
Section("Section") {
ForEach((1...100), id: \.self) {num in
TextField("text", text: $text)
.id(Field.line(num))
.focused($focus, equals: .line(num))
}
}
}
.listStyle(.insetGrouped)
.onChange(of: focus) {_ in
withAnimation {
proxy.scrollTo(focus, anchor: .center)
}
}
}
}
}
问题是:
- 为什么当定义了
@Environment(\.dismiss) private var dismiss
时,在手动来回滚动期间重建列表,而当未定义Disclose时,不会发生同样的情况? - 有什么解决方法吗:当焦点改变时,我需要能够使用ScrollProxyReader来聚焦任何文本字段,并且我需要能够关闭视图,但同时我需要避免在滚动期间不断重建列表,因为它会降低应用程序性能,滚动变得参差不齐...
P、 当定义解除并滚动列表时,美国演示应用程序不断输出"body is rebuilding",但如果任何文本字段手动获得焦点,则即使解除仍定义,也不再打印"body is rebuilding".