当新的 NSTextView 成为 FirstResponder (MacOS) 时如何移动光标?
Posted
技术标签:
【中文标题】当新的 NSTextView 成为 FirstResponder (MacOS) 时如何移动光标?【英文标题】:How to move cursor when new NSTextView becomes FirstResponder (MacOS)? 【发布时间】:2020-06-07 18:40:50 【问题描述】:每次用户按下回车键时,都会创建一个新的 NSTextView。这工作正常,新的 NSTextView 成为第一响应者,这也是我的目标。但是,尽管它是第一响应者,但光标并没有移动到新的 NSTextView 中。
下面是我的代码:
func makeNSView(context: NSViewRepresentableContext<TextView>) -> TextView.NSViewType
let textView = NSTextView()
textView.textContainer?.lineFragmentPadding = 10
textView.textContainerInset = .zero
textView.font = NSFont.systemFont(ofSize: 12)
textView.becomeFirstResponder()
//NSApp.activate(ignoringOtherApps: true) ----> doesn't make difference but is supposed to help switch cursor
print("\(textView) is first responder") //proof that the first responder is shifting, but the cursor does not move with it for some reason
return textView
我已尝试按照其他答案的建议使用此行:
NSApp.activate(ignoringOtherApps: true)
但是,它没有任何区别。我也尝试在选定范围内插入文本,但它不会在显示的任何 NSTextView 中插入文本,无论它们是否是第一响应者。
有哪些方法可以将光标移动到不同的 NSTextView(最好是第一响应者)?
如果需要更多信息,请告诉我。
【问题讨论】:
当您要求它成为第一响应者时,您的视图不是视图层次结构的一部分。将文本视图添加到窗口后成为第一响应者 【参考方案1】:通过这样做,我能够获得所需的行为:
func makeNSView(context: NSViewRepresentableContext<TextView>) -> TextView.NSViewType
let textView = NSTextView()
textView.textContainer?.lineFragmentPadding = 10
textView.textContainerInset = .zero
textView.font = NSFont.systemFont(ofSize: 12)
DispatchQueue.main.async textView.window?.makeFirstResponder(textView)
textView.setSelectedRange(NSMakeRange(0, 0))
print("\(textView) is first responder") //proof that the first responder is shifting, but the cursor does not for some reason
return textView
答案最初来自这里:How to make first responder in SwiftUI macOS
感谢大家的帮助!
【讨论】:
【参考方案2】:正如 Warren Burton 在评论中提到的那样,您尚未将新视图添加到窗口的视图层次结构中,而您正试图使其成为第一响应者。那是行不通的。
此外,调用becomeFirstResponder()
确实不会使接收者成为第一响应者。 (这与 UIKit 不同。)事实上,你永远不应该在 macOS 上调用becomeFirstResponder()
(除非在覆盖中转发到超类)。 documentation 明确指出这一点:
使用 NSWindow
makeFirstResponder(_:)
方法,而不是这个方法,使对象成为第一响应者。 切勿直接调用此方法。
(添加了重点。)becomeFirstResponder()
被 Cocoa 调用以通知视图(或其他响应者)它已成为第一响应者。它不会导致更改,它会通知更改。
因此,一旦视图被添加到窗口的视图层次结构中,调用textView.window.makeFirstResponder(textView)
。
【讨论】:
您好,感谢您的回答!我添加了 textView.window?.makeFirstResponder(textView) 来代替 textView.becomeFirstResponder()。但是,结果是一样的;光标不动。如何将视图显式添加到窗口的视图层次结构中?我可能错过了那一步。 通常,您将其添加为已经是窗口视图层次结构一部分的视图的子视图。如果新的文本视图出现在屏幕上,您必须在某处执行此操作。 嗯,上面的代码实际上是在 NSTextView 的包装器中,所以我可以在 SwiftUI 中使用它。所以我猜测视图被添加到幕后的窗口中。你知道 SwiftUI 中有什么函数会显式地向窗口的层次结构添加一个新视图吗?以上是关于当新的 NSTextView 成为 FirstResponder (MacOS) 时如何移动光标?的主要内容,如果未能解决你的问题,请参考以下文章
当新的 USB 连接/分离时,wifi 的 adb 连接被终止
当新的 API 出现时,构建一个向后兼容的 OS X 应用程序?