簡體   English   中英

Swift UI 不重繪 NSViewRepresentable 包裝的文本字段

[英]Swift UI not redrawing NSViewRepresentable wrapped textfield

我創建了一個這樣的列表詳細視圖。 在詳細視圖中,有一些接受文本的輸入字段。 輸入字段是使用NSViewRepresentable包裝的NSTextField 問題發生在以下場景中。

首先,單擊一行和 select 人 A。然后嘗試通過選擇較新的人 B 來編輯另一個人的屬性。但是這里更新的是第一個人的屬性(A)。

在此處輸入圖像描述

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 {
                    InformationView(person: PersonModel(person: selectedItem))
                } else {
                    Text("No Item Selected").foregroundColor(Color(NSColor.tertiaryLabelColor))
                }
            }
            .frame(width: 300)
            .padding()
        }
    }
}

信息視圖

struct InformationView: View {
    @ObservedObject var person: PersonModel

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

NSTextField 可表示

struct NSTextFieldRepresentable: 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: NSTextFieldRepresentable
        init(textField: NSTextFieldRepresentable) {
            self.textField = textField
        }
        
        func controlTextDidChange(_ obj: Notification) {
            textField.text = (obj.object as? NSTextField)?.stringValue ?? ""
        }
    }
}

Model class

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 測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM