更改文本字段的禁用状态时出现“AttributeGraph:检测到循环”错误

Get `AttributeGraph: cycle detected` error when changing disabled state of text field

当我在我的视图中更新 isDisabled 状态变量时,它会按预期更新我的文本字段的 .disabled 修饰符,但随后会导致大约 40 个以下错误实例出现在控制台(末尾有不同的属性编号): === AttributeGraph: cycle detected through attribute 200472 ===

然后它说:AttributeGraphError[59460:4808136] [SwiftUI] Modifying state during view update, this will cause undefined behavior.

这是产生错误的代码的最小版本:

struct ContentView: View {
  @State var isDisabled = false
  @State var text = ""
  
  var body: some View {
    VStack {
      TextField("", text: $text)
        .textFieldStyle(.roundedBorder)
        .disabled(isDisabled)

      Button("Disable text field") { isDisabled = true }
    }
  }
}

如何修复此错误?

经过几个小时的痛苦调试,我找到了解决方案!

事实证明,问题是您无法在用户仍在编辑文本字段时禁用文本字段。相反,您必须先退出文本字段(即关闭键盘),然后然后禁用文本字段。

这是我更新后的代码:

struct ContentView: View {
  @State var isDisabled = false
  @State var text = ""
  
  var body: some View {
    VStack {
      TextField("", text: $text)
        .textFieldStyle(.roundedBorder)
        .disabled(isDisabled)

      Button("Disable text field") {
        closeKeyboard()
        isDisabled = true
      }
    }
  }

  func closeKeyboard() {
    UIApplication.shared.sendAction(
      #selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil
    )
  }
}

这是一个 iOS 15+ 的解决方案。

struct ContentView: View {
    
    enum Field: Hashable {
        case text
    }
    @FocusState private var focusedField: Field?   // available iOS 15+
    
    @State var isDisabled = false
    @State var text = ""
    
    var body: some View {
        VStack {
            TextField("", text: $text)
                .focused($focusedField, equals: .text)
                .textFieldStyle(.roundedBorder)
                .disabled(isDisabled)
            
            Button("Disable text field") {
                focusedField = nil
                isDisabled = true
            }
        }
    }
}