我的应用程序中有一个 keyDown
函数,用于从名为 textInput
的 NSTextView
捕获输入。一些转换是通过将输入作为 NSAttributedString
附加到 NSTextView
中完成的。
这目前工作正常,但我遇到的问题是在 keyDown
上输入到文本框中的值没有添加到 textInput.textStorage?.string
, 直到按下另一个键。
例如,如果我在 textInput
中输入文本 abcde
且仅此而已,然后在 func keyDown()
中我尝试访问 textInput.textStorage?.string
,返回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 Bindings 与属性观察器一起使用。像这样设置您的属性:
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 }
}
}
现在将您的 TextView 绑定(bind)到 attributedTextInput
并选中“Continuously Updates Value”复选框:
Et voilà,您的属性将在您每次键入字符时立即更新,并且您的属性的 didSet
将立即被调用。
关于swift - keyDown 不会立即更新 NSTextView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46385858/