Reputation: 163
Each time the user presses enter, a new NSTextView is made. This works correctly, and the new NSTextView becomes the first responder, as is my goal. However, the cursor does not move into the new NSTextView despite it being the first responder.
Below is my code:
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
}
I have tried to use this line as suggested by a different answer:
NSApp.activate(ignoringOtherApps: true)
However, it doesn't make any difference. I have also tried inserting text at a selected range, but it doesn't insert text in any of the NSTextViews displayed regardless of whether they are the first responder.
What methods exist to move the cursor to a different NSTextView (preferably to the First Responder)?
Let me know if any more information is needed.
Upvotes: 1
Views: 763
Reputation: 163
I was able to get the desired behaviour by doing this:
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
}
The answer originally comes from here: How to make first responder in SwiftUI macOS
Thanks for all the help!
Upvotes: 1
Reputation: 90551
As Warren Burton mentions in a comment, you have not added the new view to a window's view hierarchy at the point that you're trying to make it the first responder. That can't work.
Furthermore, calling becomeFirstResponder()
does not make the receiver the first responder. (This is different from UIKit.) In fact, you're never supposed to call becomeFirstResponder()
on macOS (except to forward to the superclass in an override). The documentation calls this out specifically:
Use the NSWindow
makeFirstResponder(_:)
method, not this method, to make an object the first responder. Never invoke this method directly.
(Emphasis added.) becomeFirstResponder()
is called by Cocoa to inform a view (or other responder) that it has become the first responder. It doesn't cause a change, it notifies about a change.
So, once the view has been added to a window's view hierarchy, invoke textView.window.makeFirstResponder(textView)
.
Upvotes: 0