如何在 macOS 13 SwiftUI 中处理 MenuBarExtra 的生命周期事件

Luk*_*ine 9 menubar swift swiftui macos-ventura

我正在尝试使用新的 MenuBarExtra 在 Swift UI 中创建一个简单的额外菜单栏。我希望弹出窗口中的按钮文本在每次打开菜单时动态更新。

我正在像这样创建 MenuBarExtra 。

在此输入图像描述

        MenuBarExtra("Example menu title") {
            Button("Item 1") {
              
            }
            
            Button("Item 2") {
              
            }
            
            Button("Item 3") {
              
            }
        }
Run Code Online (Sandbox Code Playgroud)

我希望每次打开菜单时按钮文本(即第 1 项)都会更改。我本来希望 onAppear 每次打开菜单时都会触发,但它只在第一次时触发。首次打开弹出窗口后,没有明确的方法来检测菜单关闭或打开事件。

我尝试使用各种事件处理回调来检测弹出窗口的打开。OnAppear 用于检测视图的初始创建,而 onDisappear 则从未被调用。

    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")
        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 -1

根据Apple 的 DocsMenuBarExtra符合Scene- 这意味着每次 MenuBarExtra 进入前台或后台时,您都可以使用Environment变量来调用某些内容。ScenePhase文章来源:https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-when-your-app-moves-to-the-background-or-foreground-with-scenephase。用法示例:

@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")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 尝试了一下,不幸的是它不适用于 MenuBarExtra。如果我在 WindowGroup 内的 ContentView 上设置 onChange,它会完全按预期工作。如果我将相同的 ContentView 传递给 MenuBarExtra 它会停止打印。 (2认同)