我创建了这样的列表详细视图.在细节视图中,有一些输入字段接受文本.输入字段是用NSViewRepresentable包装的NSTextField.问题发生在下面的场景中.

首先,单击一行并 Select 人员a.然后try 通过 Select 较新的人员B来编辑另一个人的属性.但在这里,第一个人的属性(a)发生了更新.

enter image description here

struct ContentView: View {
    @State var selectedItem: Person?
    var body: some View {
        HStack {
            List(selection: $selectedItem) {
                ForEach(modelData, id: \.self) {  person in
                    Text(person.firstName)
                }
            }
            .border(.separator, width: 1)
            .listStyle(.plain)
            .padding()
            .frame(width: 200)
            
            VStack {
                if let selectedItem = selectedItem {
                    信息视图(person: PersonModel(person: selectedItem))
                } else {
                    Text("No Item Selected").foregroundColor(Color(NSColor.tertiaryLabelColor))
                }
            }
            .frame(width: 300)
            .padding()
        }
    }
}

信息视图

struct 信息视图: View {
    @ObservedObject var person: PersonModel

    var body: some View {
        Form {
            NSTextField可表示(placeholder: "", text: $person.person.firstName)
            NSTextField可表示(placeholder: "", text: $person.person.secondName)
            NSTextField可表示(placeholder: "", text: $person.person.city)
        }
    }
}

NSTextField可表示

struct NSTextField可表示: NSViewRepresentable {
    let placeholder: String
    @Binding var text: String
    
    func makeNSView(context: Context) -> NSTextField {
        let view = NSTextField()
        view.delegate = context.coordinator
        return view
    }
        
    func updateNSView(_ nsView: NSTextField, context: Context) {
        nsView.stringValue = text
        nsView.placeholderString = NSLocalizedString(placeholder, comment: "")
    }
    
    func makeCoordinator() -> NSTextFieldCoordinator {
        NSTextFieldCoordinator(textField: self)
    }

    class NSTextFieldCoordinator: NSObject, NSTextFieldDelegate {
        var textField: NSTextField可表示
        init(textField: NSTextField可表示) {
            self.textField = textField
        }
        
        func controlTextDidChange(_ obj: Notification) {
            textField.text = (obj.object as? NSTextField)?.stringValue ?? ""
        }
    }
}

模型类

class Person: NSObject, Identifiable {
    
    var id = UUID()
    var firstName: String
    var secondName: String
    var city: String
    
    init (firstName: String, secondName: String, city: String) {
        self.firstName = firstName
        self.secondName = secondName
        self.city = city
    }
}


var modelData: [Person] = [
    Person(firstName: "Lionel", secondName: "Messi", city: "Paris"),
    Person(firstName: "Cristiano", secondName: "Ronaldo", city: "Manchester"),
    Person(firstName: "Sachin", secondName: "Tendulkar", city: "Mumbai"),
    Person(firstName: "Virat", secondName: "Kohli", city: "Delhi")
]

class PersonModel: ObservableObject {
    @Published var person: Person
    init(person: Person) {
        self.person = person
    }
    
}

推荐答案

在这里

    init(textField: NSTextFieldRepresentable) {
        self.textField = textField         // << copy !!
    }

self.textField是视图的副本,但在绑定更改时,NSTextFieldRepresentable不会重新创建-只有updateNSView被调用以刷新本机部分,因此协调器在创建时仍然具有复制的值.这就是问题所在.

此设计中的一个可能修复方法是在绑定更改时更新协调器:

func updateNSView(_ nsView: NSTextField, context: Context) {
    nsView.stringValue = text
    nsView.placeholderString = NSLocalizedString(placeholder, comment: "")

    context.coordinator.textField = self  // << here !!
}

使用Xcode 13.4/macOS 12.4测试

Swift相关问答推荐

按Esc键时执行操作(工作表)

字符串目录不适用于SWIFT包

SWIFT闭包使用的是陈旧的值,即使它是S@转义

调度组是否阻止iOS中的主线程?

表视图插座单元测试失败

SwiftUI 交易:根据外部状态制作一个动画或静止的按钮

子视图未在父视图 SwiftUI 中触发禁用状态更新

有没有一种方法可以访问封闭实例ObservableObject以从属性包装器中的任何位置调用objectWillChange.send()

一组可散列的自定义元素插入相等的元素

响应 UITextField (UIViewRepresentable) 中的特定按键

如何让 SwiftUI 中的文本在旋转框架的同时侧向显示?

在 xcode 13 中的构建之间保持可访问性权限

如果没有标记,则为 Swift 预处理器

在 Xcode 中自动实现 Swift 协议方法

FCM 后台通知在 iOS 中不起作用

Swift 3.0 的 stringByReplacingOccurencesOfString()

Swift 3:日期与 NSDate?

在 Swift 中,你可以用另一个字符串分割一个字符串,而不仅仅是一个字符吗?

如何使用 Swift 枚举作为字典键? (符合 Equatable)

swift中静态函数和单例类的区别