简体   繁体   中英

How to handle lifecycle events for MenuBarExtra in macOS 13 SwiftUI

I'm trying to create a simple menu bar extra in Swift UI using the new MenuBarExtra. I would like the button text in the popover to update dynamically every time the menu is open.

I'm creating the MenuBarExtra like this.

在此处输入图像描述

        MenuBarExtra("Example menu title") {
            Button("Item 1") {
              
            }
            
            Button("Item 2") {
              
            }
            
            Button("Item 3") {
              
            }
        }

I would like the button text (ie. Item 1) to change every time the menu is open. I would have expected onAppear to fire every time the menu is open, but it only fires the first time. After the initial opening of the popover, there is no clear way to detect a menu close or open event.

I have tried using the various event handling callbacks to detect the popover opening. OnAppear works for detecting the initial creation of the view while onDisappear is notably never called.

    MenuBarExtra("Example menu title") {
        VStack {
            Button("Item 1") {
                
            }
            
            Button("Item 2") {
                
            }
            
            Button("Item 3") {
                
            }
        }.onAppear() {
            print("This only prints the very first time the menu is opened")
        }
    }

According to Apple's Docs , MenuBarExtra conforms to Scene - this means that you can use an Environment variable of ScenePhase to call something every time the MenuBarExtra enters the foreground or background. Article source: https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-when-your-app-moves-to-the-background-or-foreground-with-scenephase . Example usage:

@main
struct AppWithMenuBarExtra: App {
@Environment(\.scenePhase) var scenePhase // <-- HERE! This will give you the values

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        MenuBarExtra(
            "App Menu Bar Extra", systemImage: "star")
        {
            StatusMenu()
.onChange(of: scenePhase) { newPhase in //<-- HERE TOO! This modifier allows you to detect change of scene.
                if newPhase == .inactive {
                    //Code for moved to inactive
                    print("Moved to inactive")
                } else if newPhase == .active {
                    //Code for moved to foreground
                    print("Moved to foreground - now active")
                    //This is where you would want to change your text
                } else if newPhase == .background {
                    //Code for moved to background
                    print("Moved to background")
                }
            }
        }
    }
}

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