【发布时间】:2021-05-16 07:14:41
【问题描述】:
在表单中,我希望用户能够动态维护电话号码列表,包括根据需要添加/删除号码。
我目前正在维护 ObservableObject 类的已发布数组属性中的数字列表,这样当向数组中添加新数字时,SwiftUI 表单将通过其 ForEach 循环重建列表。 (每个电话号码都表示为一个PhoneDetails 结构,具有号码本身和电话类型[工作、手机等] 的属性。)
添加/删除非常好,但是当我尝试在 TextField 中编辑电话号码时,只要我输入一个字符,TextField 就会失去焦点。
我的直觉是,由于 TextField 绑定到其中一个数组项的 phoneNumber 属性,所以一旦我修改它,类中的整个数组就会发布它已被更改的事实,因此 SwiftUI 会尽职尽责地重建ForEach 循环,从而失去焦点。尝试输入新电话号码时,这种行为并不理想!
我还尝试直接循环遍历 PhoneDetails 对象的数组,而不使用 ObservedObject 类作为中间存储库,并且相同的行为仍然存在。
以下是最小可重现的示例代码;如前所述,添加/删除项目效果很好,但尝试输入任何 TextField 会立即失去焦点。
有人可以帮我指出我做错了什么的正确方向吗?
class PhoneDetailsStore: ObservableObject {
@Published var allPhones: [PhoneDetails]
init(phones: [PhoneDetails]) {
allPhones = phones
}
func addNewPhoneNumber() {
allPhones.append(PhoneDetails(phoneNumber: "", phoneType: "cell"))
}
func deletePhoneNumber(at index: Int) {
if allPhones.indices.contains(index) {
allPhones.remove(at: index)
}
}
}
struct PhoneDetails: Equatable, Hashable {
var phoneNumber: String
var phoneType: String
}
struct ContentView: View {
@ObservedObject var userPhonesManager: PhoneDetailsStore = PhoneDetailsStore(
phones: [
PhoneDetails(phoneNumber: "800–692–7753", phoneType: "cell"),
PhoneDetails(phoneNumber: "867-5309", phoneType: "home"),
PhoneDetails(phoneNumber: "1-900-649-2568", phoneType: "office")
]
)
var body: some View {
List {
ForEach(userPhonesManager.allPhones, id: \.self) { phoneDetails in
let index = userPhonesManager.allPhones.firstIndex(of: phoneDetails)!
HStack {
Button(action: { userPhonesManager.deletePhoneNumber(at: index) }) {
Image(systemName: "minus.circle.fill")
}.buttonStyle(BorderlessButtonStyle())
TextField("Phone", text: $userPhonesManager.allPhones[index].phoneNumber)
}
}
Button(action: { userPhonesManager.addNewPhoneNumber() }) {
Label {
Text("Add Phone Number")
} icon: {
Image(systemName: "plus.circle.fill")
}
}.buttonStyle(BorderlessButtonStyle())
}
}
}
【问题讨论】:
-
我确实发现 this SO post 提出了类似的问题,但其接受的答案无助于解决我的问题。
标签: swiftui