我有NSTextViews,需要在其中跟踪文本的当前端点以放置界面元素。
我将模型字符串绑定到文本视图上的NSBindingName.value。
在编辑文本后,我会在
中更新界面元素的位置func textDidChange(_ notification: Notification)
...作为NSTextView的委托。
但是,如果我的模型是字符串更新的源,则即使在NSTextView中正确更新了文本,也不会调用此委托方法。
所以,我做错什么了吗,绑定的更改应该调用textDidChange吗?
如果不是,并且这是一个错误或特意设计,我是否应该观察并手动更新值并通过自己的委托方法进行调用?失去绑定的优雅似乎很可惜。
请注意,之前曾有人问过此问题,但如果不是NSTextView textDidChange/didChangeText not called for bindings
,则将其标记为正确答案答案 0 :(得分:0)
当绑定更新文本(而不是文本视图更新模型)时,不调用NSTextView方法didChangeText。
didChangeText是绑定更新的源。如果您覆盖它并且不调用super,则绑定会中断。 didChangeText调用委托方法textDidChange。
不幸的是,在NSTextView更新过程的后期(在布局和存储委托调用之后),didChangeText也被调用。
这让我感到沮丧,因为在我打电话给代表之前,我需要更改模型-我正在用另一个视图对NSTableView行高进行单独的计算。如果这些是在模型更新之前完成的,那么我的高度会错误。
我发现无法从NSTextView代码中区分字符串的模型更新和textview更新。我以NSTextStorage委托的形式在didProcessEditing中捕获了对字符串的所有更新。
func textStorage(_ textStorage: NSTextStorage,
didProcessEditing editedMask: NSTextStorageEditActions,
range editedRange: NSRange,
changeInLength delta: Int)
{
if editedMask.contains(.editedCharacters) {
textStringDidChange = true
}
}
我只是在这里设置了一个标志,因为如果他们尝试以任何方式更新NSTextView,对我的委托的调用都会崩溃。然后,我在以下NSLayoutManagerDelegate调用中使用了此标志:
func layoutManagerDidInvalidateLayout(_ sender: NSLayoutManager)
{
if textStringDidChange {
delegate?.textDidChange?(Notification(name: .init("")))
textStringDidChange = false
}
}
在这些委托调用之后的某个时间调用didChangeText。因此,我不得不处理文本视图初始化的更改,两次调用我的代表。它效率低下,但我找不到将其过滤掉的方法。