【发布时间】:2020-05-31 12:36:41
【问题描述】:
假设我有:
- 结构体
Document,代表文本文档。 -
EditorView— 一个NSTextView,用 Combine 包裹,绑定到Document.content<String>。
Document 是复杂store:ObservableObject 的一部分,因此它可以绑定到EditorView 实例。
当我第一次创建绑定时,它按预期工作——编辑 NSTextView 会更改 Document.content 中的值。
let document1 = Document(...)
let document2 = Document(...)
var editor = EditorView(doc: document1)
但是如果更改绑定到另一个文档...
editor.doc = document2
...然后updateNSView 可以看到新的document2。但是在 Coordiantor 的textDidChange 里面还是有对document1 的引用。
func textDidChange(_ notification: Notification) {
guard let textView = notification.object as? NSTextView else {
return
}
self.parent.doc.content = textView.string
self.selectedRanges = textView.selectedRanges
}
所以,最初,当我设置新的 bindint 时,NSTextView 将其内容更改为 document2,但当我键入时,协调器将更改发送到 document1。
Coordiantor 是否保留了自己的 parent 副本,即使父级更改(@Binding doc 已更新),它仍然引用旧的?
如何让 Coordinator 反映父级绑定的变化?
谢谢!
struct Document: Identifiable, Equatable {
let id: UUID = UUID()
var name: String
var content: String
}
struct EditorView: NSViewRepresentable {
@Binding var doc: Document
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: Context) -> CustomTextView {
let textView = CustomTextView(
text: doc.content,
isEditable: isEditable,
font: font
)
textView.delegate = context.coordinator
return textView
}
func updateNSView(_ view: CustomTextView, context: Context) {
view.text = doc.content
view.selectedRanges = context.coordinator.selectedRanges
}
}
// MARK: - Coordinator
extension EditorView {
class Coordinator: NSObject, NSTextViewDelegate {
var parent: EditorView
var selectedRanges: [NSValue] = []
init(_ parent: EditorView) {
self.parent = parent
}
func textDidBeginEditing(_ notification: Notification) {
guard let textView = notification.object as? NSTextView else {
return
}
self.parent.doc.content = textView.string
self.parent.onEditingChanged()
}
func textDidChange(_ notification: Notification) {
guard let textView = notification.object as? NSTextView else {
return
}
self.parent.doc.content = textView.string
self.selectedRanges = textView.selectedRanges
}
func textDidEndEditing(_ notification: Notification) {
guard let textView = notification.object as? NSTextView else {
return
}
self.parent.doc.content = textView.string
self.parent.onCommit()
}
}
}
// MARK: - CustomTextView
final class CustomTextView: NSView {
private var isEditable: Bool
private var font: NSFont?
weak var delegate: NSTextViewDelegate?
var text: String {
didSet {
textView.string = text
}
}
// ...
【问题讨论】:
标签: swift swiftui appkit combine