首页 > 解决方案 > SwiftUI 中的 onReceive 与 ObservableObjects/State/Binding 数组导致无限循环

问题描述

我正在使用.onReceive(_:perform:)在我的文本字段文本中添加模式掩码。ObservableObjects当我使用, Binding,State对象或Published属性的数组时会发生无限循环。

例子

struct MyTextField: View {
    @Binding var text: String
    
    ...
}

extension MyTextField {
    func mask(_ mask: String) -> some View {
        self.onReceive(Just(text)) { newValue in

            // `string(withMask:)` returns another string (already formatted correctly)
            text = newValue.string(withMask: mask) // Obviously when I comment this line of code, the problem stops
        }
    }
}

用法

final class FormItem: ObservableObject, Identifiable {
    let id = UUID()
    
    @Published var text = ""
    let mask: String
    
    init(mask: String) {
        self.mask = mask
    }
}
@State var volunteerForm: [FormItem] = [
    FormItem(mask: "999.999.999-99")
]


var body: some View {
   VStack {
      ForEach(volunteerForm.indices, id: \.self) { index in
         MyTextField("", text: volunteerForm[index].$text, onCommit: onCommit)
            .mask(volunteerForm[index].mask)
      }
   }

}

但是当我像这样使用单个属性时@State var formItem: FormItem = ...,不会发生这种无限循环。此外,当我使用数组String而不是 Class 的数组时FormItem@State var volunteerTexts: [String] = [""]它也不会发生。

我想知道当我们使用自定义structclass.

我尝试创建没有ObservableObjectand的模型Published,就像结构一样,但无限循环不断发生:

struct FormItem: Identifiable {
    let id = UUID()
    
    var text = ""
    let mask: String
}
VStack {
   ForEach(volunteerForm.indices, id: \.self) { index in
      TextField("", text: $volunteerForm[index].text, onCommit: onCommit)
         .mask(volunteerForm[index].mask)
   }
}

你知道为什么会发生这个无限循环吗?

标签: iosswiftswiftui

解决方案


推荐阅读