macosswiftuimacbookpro-touch-bar

How can I display Touch Bar Buttons using SwiftUI?


I'm trying to add Touch Bar support for a SwiftUI View. There seems to be SwiftUI API for this using the .touchBar(content: () -> View) function on Views, but documentation is non existent and I can't get my Touch Bar to display anything.

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, World!")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .touchBar {
                Button(action: {

                }) {
                    Text("do something")
                }
        }
    }
}

This code does compile and run, but the Touch Bar remains empty. How can I get my touch bar to display content using SwiftUI (not catalyst)?


Solution

  • Using .focusable doesn't work without "Use keyboard navigation to move focus between controls" checked in System Preferences -> Keyboard -> Shortcuts. To work around that, I did this:

    /// Bit of a hack to enable touch bar support.
    class FocusNSView: NSView {
        override var acceptsFirstResponder: Bool {
            return true
        }
    }
    
    /// Gets the keyboard focus if nothing else is focused.
    struct FocusView: NSViewRepresentable {
    
        func makeNSView(context: NSViewRepresentableContext<FocusView>) -> FocusNSView {
            return FocusNSView()
        }
    
        func updateNSView(_ nsView: FocusNSView, context: Context) {
    
            // Delay making the view the first responder to avoid SwiftUI errors.
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
                if let window = nsView.window {
    
                    // Only set the focus if nothing else is focused.
                    if let _ = window.firstResponder as? NSWindow {
                        window.makeFirstResponder(nsView)
                    }
                }
            }
        }
    }