具有文本字段绑定和焦点状态的动态列表导致 iOS 18 上的无限循环

问题描述 投票:0回答:1

我有一个完美工作的列表,其中包含动态数据和一个文本字段,其中一行具有绑定和焦点状态。

自 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 swift swiftui binding swiftui-list
1个回答
0
投票

我发布答案,以便从 iOS 17 更新到 18 时遇到相同问题的任何人都能找到答案。

正如 @Sweeper 在评论中所说,问题来自于 ID 是一个计算属性。每次重画后都会生成一个新的ID。

以下更改解决了该问题:

  final class Row: ObservableObject, Identifiable {
    @Published var text: String = ""

    let id: String = UUID().uuidString
  }

使用计算属性没有意义,但奇怪的是我们之前在 iOS 17 上从未遇到过这个问题。iOS 18 检测视图需要重绘的方式肯定发生了变化。

© www.soinside.com 2019 - 2024. All rights reserved.