8

Consider this macOS app code implemented with app delegate lifecycle:

App delegate:

func applicationDidFinishLaunching(_ aNotification: Notification) {
        let contentView = ContentView()
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.toolbar = NSToolbar(identifier: "toolbar")
        window.title = "hello title"
        window.subtitle = "hello subtitle"
        window.isReleasedWhenClosed = false
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

SwiftUI:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(
                    destination: ItemView(),
                    label: {
                        Label("Something", systemImage: "folder.circle")
                    })
                NavigationLink(
                    destination: ItemView(),
                    label: {
                        Label("Another", systemImage: "pencil.tip.crop.circle")
                    })
            }.listStyle(SidebarListStyle())
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .toolbar {
            ToolbarItem {
                Button(action: {
                    print("Button clicked")
                }, label: {
                    Label("Hello", systemImage: "pencil.circle")
                })
            }
        }
    }
}
struct ItemView: View {
    var body: some View {
        Text("Hello, World!")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .toolbar {
                ToolbarItem {
                    Button(action: {
                        print("Item button")
                    }, label: {
                        Label("Itemtool", systemImage: "lock.doc")
                    })
                }
            }
    }
}

What this does: correctly sets up the window and toolbar look. Toolbar has no buttons though. It looks like this:

Test window

What I would like to do: get the toolbar items added from SwiftUI added to the toolbar.

Everything works as expected when I have the window managed by the SwiftUI app lifecycle. However, I need to stick with the app delegate lifecycle for unrelated reasons.

Is this possible? How do I add toolbar buttons from SwiftUI to the toolbar of window that is created by app delegate?

Jaanus
  • 17,688
  • 15
  • 65
  • 110

1 Answers1

-2

On macOS 11 beta 6 and Xcode 12 beta 6:

ContentView:

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(
                    destination: ItemView(),
                    label: {
                        Label("Something", systemImage: "folder.circle")
                    })
                NavigationLink(
                    destination: ItemView(),
                    label: {
                        Label("Another", systemImage: "pencil.tip.crop.circle")
                    })
            }.listStyle(SidebarListStyle())
            .toolbar {
                ToolbarItem {
                    Button(action: {
                        print("Button clicked")
                    }, label: {
                        Label("Hello", systemImage: "pencil.circle")
                    })
                }
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        /* move into the NavigationView
        .toolbar {
            ToolbarItem {
                Button(action: {
                    print("Button clicked")
                }, label: {
                    Label("Hello", systemImage: "pencil.circle")
                })
            }
        }
        */
 
    }
}

struct ItemView: View {
    var body: some View {
        Text("Hello, World!")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .navigationTitle("hello title")  // add title
            .navigationSubtitle("hello subtitle")  // add sub title
            .toolbar {
                ToolbarItem {
                    Button(action: {
                        print("Item button")
                    }, label: {
                        Label("Itemtool", systemImage: "lock.doc")
                    })
                }
            }
    }
}

And you need a class for Appdelegate:

class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
    // do something
    }

    // others func

}

Last:

@main
struct SomeApp: App {
    
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Result:

enter image description here

sugimoto
  • 40
  • 1
  • 1
  • 3
    This shows how to add the toolbar buttons with the new SwiftUI app lifecycle. This works fine for me. My question is how to do it with App Delegate lifecycle (there is no SomeApp class, no App subclass). – Jaanus Sep 13 '20 at 12:31