11

How is it possible to make a View on macOS focusable. I tried the it like below but the action is never triggered. I know that for NSView you have to implement acceptsFirstResponder to return true but can not find similar in SwiftUI.

Is this still a Beta related bug or a missing functionality for macOS ?

struct FocusableView: View {

    var body: some View {
        Group {
            Text("Hello World!")
                .padding(20)
                .background(Color.blue.cornerRadius(8))
            .focusable(true) { isFocused in
                print("Focused", isFocused)
            }
        }
    }
}

Marc T.
  • 5,090
  • 1
  • 23
  • 40

2 Answers2

5

I think I found a work around for the problem to shift the focus to a SwiftUI view. I am working on macOS Catalina, 10.15, Swift 5, Xcode 11.1

The problem is to shift the focus to a SwiftUI view. I could imagine that this has not been perfectly implemented, yet.

Only upon shifting the focus to the required SwiftUI view within the SwiftUI framework the onFocusChange closure of a focusable view will be called and the view will be focused.

My intention was: when I click into the SwiftUI view I want to execute the onFocusChange closure and I want it to be focused (for subsequent paste commands)

My SwiftUI view is built into the Window using an NSHostingView subclass - ImageHostingView.

  1. When I add this ImageHostingView to the view hierarchy I define its previous key view:

    theImageHostingView.superview.nextKeyView = theImageHostingView
    
  2. I added a mouseDown handler to the ImageHostingView:

    override dynamic func mouseDown(with event: NSEvent) {
      if let theWindow = self.window, let theView = self.previousValidKeyView {
      theWindow.selectKeyView(following:theView)
     }
    }
    

Calling the NSWindow's selectKeyView(following:) triggers within the SwiftUI framework a focus change to the desired view (the root view of ImageHostingView).

This is clearly a work-around and works only for final views which will be represented by a NSHostingView. But it highlights the problem (shifting the focus to a SwiftUI view upon a certain action) and it might be helpful in many cases.

M Wilm
  • 184
  • 7
4

The only way I've been able to get this to work is by checking the "Use keyboard navigation to move focus between controls" checkbox in Keyboard System Preferences

enter image description here