简体   繁体   中英

How do I add items to NSToolbar with SwiftUI?

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:

测试窗口

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM