我有一个完美工作的列表,其中包含动态数据和一个文本字段,其中一行具有绑定和焦点状态。
自 iOS 18 起,加载此列表将在第一次加载时由于绑定值的不断更新而导致无限循环,尽管我此时没有更新它。
这是一个重现 iOS 18 之前运行良好的问题的示例:
struct MyTextFieldView: View {
@Binding var text: String
@FocusState private var isFocused: Bool
private let title: String
init(title: String,
text: Binding<String>) {
self.title = title
self._text = text
}
var body: some View {
TextField(title, text: $text)
.focused($isFocused)
.keyboardType(.asciiCapable)
}
}
struct ListView: View {
final class Row: ObservableObject, Identifiable {
@Published var text: String = ""
var id: String {
UUID().uuidString
}
}
@State private var data: [Row] = [
.init(),
.init()
]
var body: some View {
List($data) { row in
Section {
MyTextFieldView(title: row.id,
text: row.text)
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: ListView()) {
Text("Go to list")
}
}
}
}
用静态列表替换动态列表时,它不会无限循环:
List {
Section {
MyTextFieldView(title: "1",
text: $text)
}
}
有人可以帮助我了解发生了什么事吗?
我发布答案,以便从 iOS 17 更新到 18 时遇到相同问题的任何人都能找到答案。
正如 @Sweeper 在评论中所说,问题来自于 ID 是一个计算属性。每次重画后都会生成一个新的ID。
以下更改解决了该问题:
final class Row: ObservableObject, Identifiable {
@Published var text: String = ""
let id: String = UUID().uuidString
}
使用计算属性没有意义,但奇怪的是我们之前在 iOS 17 上从未遇到过这个问题。iOS 18 检测视图需要重绘的方式肯定发生了变化。