keyDown 不会立即更新 NSTextView

keyDown doesn't update NSTextView immediately

我的应用程序中有一个 keyDown 函数,用于捕获来自名为 textInputNSTextView 的输入。一些转换是通过将输入作为 NSAttributedString 附加回 NSTextView.

完成的

这目前工作正常,但我遇到的问题是在 keyDown 的文本框中输入的值不会添加到 textInput.textStorage?.string,直到按下另一个键。

例如,如果我在 textInput 中输入文本 abcde,仅此而已,然后在 func keyDown() 中尝试访问 textInput.textStorage?.string,它将 return abcd.

下面是去掉不必要部分的函数:

override func keyDown(with event: NSEvent) {
    let bottomBox = textInput.textStorage?.string // This returns one character short of what is actually in the text box

    if let bottomBox = bottomBox {
        var attribute = NSMutableAttributedString(string: bottomBox)

        // Do some stuff here with bottomBox and attribute

        // Clear and set attributed string
        textInput.textStorage?.mutableString.setString("")
        textInput.textStorage?.append(attribute)
    }
}

如果我使用 keyUp,这不是问题,尽管 keyUp 的问题是如果用户按住该键,NSAttributedString 上的属性] 在用户释放密钥之前不要设置。

我虽然可能有一种方法可以在 keyDown 函数期间以编程方式释放 keyDown 事件,或者生成 keyUp 事件,但似乎找不到任何东西。

有办法解决这个问题吗?

我喜欢做的是使用 Cocoa 与 属性 观察者的绑定。像这样设置您的属性:

class MyViewController: NSViewController {
    @objc dynamic var textInput: String {
        didSet { /* put your handler here */ }
    }

    // needed because NSTextView only has an "Attributed String" binding
    @objc private static let keyPathsForValuesAffectingAttributedTextInput: Set<String> = [
        #keyPath(textInput)
    ]
    @objc private var attributedTextInput: NSAttributedString {
        get { return NSAttributedString(string: self.textInput) }
        set { self.textInput = newValue.string }
    }
}

现在将您的文本视图绑定到 attributedTextInput,并选中 "Continuously Updates Value" 复选框:

Et voilà,您的 属性 将在您每次键入字符时立即更新,并且您的 属性 的 didSet 将立即被调用。