I am trying to create a TextView to use with SwiftUI and have use the code shown below to create the TextView.
This all seems to work fine except that the TextView retains the binding to the first object for all the updates.
For example if the TextView is used I a Master Detail arrangement then it will always update the first object that was selected. It seems the binding does not update to subsequent objects.
I have created a small sample application you can test out here. Run the app and select one of the objects in the left panel list and then try editing the textView and the textField. The text fields work as expected but the textView does not.
https://duncangroenewald.com/files/SampleApps/TextView.zip
import SwiftUI
// OSTextView is a subclass of NSTextView - but just use NSTextView if required
#if !os(macOS)
struct TextView: UIViewRepresentable {
@Binding var attributedText: NSAttributedString
func makeUIView(context: Context) -> OSTextView {
let textView = OSTextView()
textView.delegate = context.coordinator
return textView
}
func updateUIView(_ uiView: OSTextView, context: Context) {
uiView.attributedText = attributedText
}
func makeCoordinator() -> Coordinator {
Coordinator($attributedText)
}
class Coordinator: NSObject, UITextViewDelegate {
var text: Binding<NSAttributedString>
init(_ text: Binding<NSAttributedString>) {
self.text = text
}
func textViewDidChange(_ textView: UITextView) {
self.text.wrappedValue = textView.attributedText
}
}
}
#endif
#if os(macOS)
struct TextView: NSViewRepresentable {
@Binding var attributedText: NSAttributedString
func makeNSView(context: Context) -> OSTextView {
let textView = OSTextView(frame: .zero)
textView.delegate = context.coordinator
return textView
}
func updateNSView(_ nsView: OSTextView, context: Context) {
nsView.textStorage?.setAttributedString(attributedText)
}
func makeCoordinator() -> Coordinator {
return Coordinator($attributedText)
}
class Coordinator: NSObject, NSTextViewDelegate {
var text: Binding<NSAttributedString>
init(_ text: Binding<NSAttributedString>) {
self.text = text
super.init()
}
func textDidChange(_ notification: Notification) {
if let textView = notification.object as? NSTextView {
self.text.wrappedValue = textView.attributedString()
}
}
}
}
#endif