感谢@Willeke 的回答,我已经找到了解决方案。然而,这很棘手:
- 首先,子类
NSTextField 保留另一个NSTouchBar:
class MyTextField: NSTextField
{
private var innerTouchBar: Any?
var editor: NSText?
@available(OSX 10.12.2, *)
func setTouchBar(_ touchBar: NSTouchBar?)
{
innerTouchBar = touchBar
}
@available(OSX 10.12.2, *)
func getTouchBar() -> NSTouchBar?
{
innerTouchBar as? NSTouchBar
}
}
- 然后,子类
NSTextView 使用提供的NSTouchBar:
@available(OSX 10.12.2, *)
class MyTextView: NSTextView
{
private var innerTouchBar: NSTouchBar?
convenience init(touchBar: NSTouchBar?)
{
self.init()
innerTouchBar = touchBar
}
override func makeTouchBar() -> NSTouchBar?
{
innerTouchBar
}
}
- 当
NSWindowController 被要求提供NSTextField 的NSTextView 时,然后使用NSTextField 的innerTouchBar 创建一个自定义NSTextView:
extension MyWindowController
{
func windowWillReturnFieldEditor(_ sender: NSWindow, to client: Any?) -> Any?
{
if #available(OSX 10.12.2, *)
{
if let field = client as? MyTextField
{
if field.editor == nil
{
field.editor = SFTextView(touchBar: field.getTouchBar())
field.editor?.isFieldEditor = true
}
return field.editor
}
}
return nil;
}
}
- 当然,不要忘记在XIB或代码中使用
MyTextField而不是NSTextField,并在创建后首先调用setTouchBar(_:)函数。
说明
每个NSTextField 都有一个底层NSTextView,它实际上是firstResponder,也是显示touchBar 的对象。我们不能直接从NSTextField 访问底层NSTextView。相反,NSTextField 询问NWindowController 使用哪个NSTextView。因此,当这种情况发生时,在NSWindowController 的windowWillReturnFieldEditor(_:,to:) 中,我们必须返回一个带有正确触摸栏的自定义NSTextView。
我认为这可以适用于 touchBar 以外的其他东西...