我正在编写一个 MenuBarExtra ,它需要知道当前的应用程序。我有一些代码几乎可以完成这项工作:
import SwiftUI
@main
struct XBApp: App {
@State var bundleID: String = ""
var body: some Scene {
MenuBarExtra("Something", systemImage: "questionmark.bubble") {
VStack {
XBContent(bundleID: bundleID)
.padding(0)
}
.onAppear {
bundleID = NSWorkspace.shared.frontmostApplication!.bundleIdentifier!
print("\(#fileID):\(#line) - \(bundleID)")
}
}
.menuBarExtraStyle(.window)
}
}
struct XBContent: View {
var bundleID: String = ""
@State var data: String = ""
init(bundleID: String) {
self.bundleID = bundleID // store received value
}
var body: some View {
VStack {
Text(bundleID) // current value
Text(data) // previous value
}
.onAppear {
data = bundleID // copy value
print("\(#fileID):\(#line) - \(bundleID) | \(data)")
}
}
}
主应用程序在
.onAppear
中设置当前的 Bundle id,然后将其传递到 XBContent
视图。我认为这部分工作正确,但我愿意接受纠正。
XBContent
视图仅显示传递的包ID的两个版本:
init()
方法将值存储在属性中。onAppear
将其复制到另一个变量中进行测试。在现实生活中,它应该使用这个值来读取一些其他数据。VStack
显示来自 init()
的值以及来自 onAppear
的复制值。问题来了:从
onAppear
复制的值总是落后一步。当应用程序首次启动并打开额外的菜单栏时,第一个值是正确的,而第二个值是默认的空字符串;这个问题下次就解决了。当我切换到另一个应用程序并额外打开菜单栏时,第一个值是正确的新捆绑包 ID,而第二个值是旧的,直到我再次尝试,就可以了。
据我所知,当我认为应该触发时,
onAppear
却没有被触发。
如何才能使第二个值成为正确的值?
使用
@Binding var bundleID: String
尝试此方法。请注意,不需要 init(...)
中的 XBContent
,视图会为您完成这一切。
@main
struct XBApp: App {
@State private var bundleID: String = "" // <--- here
var body: some Scene {
MenuBarExtra("Something", systemImage: "questionmark.bubble") {
VStack {
XBContent(bundleID: $bundleID) // <--- here
.padding(0)
}
.onAppear {
bundleID = NSWorkspace.shared.frontmostApplication!.bundleIdentifier!
print("\(#fileID):\(#line) - \(bundleID)")
}
}
.menuBarExtraStyle(.window)
}
}
struct XBContent: View {
@Binding var bundleID: String // <--- here
@State private var data: String = "" // <--- here
var body: some View {
VStack {
Text(bundleID)
Text(data)
}
.onAppear {
data = bundleID // copy value
print("\(#fileID):\(#line) - \(bundleID) | \(data)")
}
}
}