我正在使用macOS Montery Beta 4和Xcode 13 Beta 4,我想我在SwiftUI
中发现了一个错误。
当使用CommandGroup
和根据条件启用/禁用的按钮时,CommandGroup
不会更新。然而CCD_ 4确实如此。
复制:
- 创建一个新的SwiftUI macOS项目
- 在
App
文件中粘贴以下代码:
class Test: ObservableObject {
@Published var num = 0
}
@main
struct TestApp: App {
@StateObject private var test = Test()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(test)
}
.commands {
CommandGroup(after: .newItem) {
Button(action: {}) {
Text("Test menu item")
}
.disabled(test.num == 0)
}
}
}
}
- 在
ContentView
文件中粘贴以下代码:
struct ContentView: View {
@EnvironmentObject var test: Test
var body: some View {
Button(action: {
test.num += 1
}) {
Text(String(test.num) + " ---------")
}
}
}
- 运行应用程序,然后单击
File
菜单。你应该看到";测试菜单项";按预期禁用 - 单击按钮。这只是将一个数字增加1。然而;测试菜单项";即使
test.num
!=0
问题是,用CommandMenu("Test menu")
替换CommandGroup
可以修复它
该应用程序所做的只是有一个菜单项,如果数字为零,该菜单项将被禁用。按下按钮会使该数字不为零,但菜单项将保持禁用状态。
有人能复制这个吗?这是我的错误吗?
@George_E答案的一个小变化是:
CommandGroup(after: .newItem) {
TestView(test: test)
}
struct TestView: View {
@ObservedObject var test: Test
var body: some View {
Button(action: {}) {
Text("Test menu item")
}
.disabled(test.num == 0)
}
}
我不认为这是预期行为。但是,我找到了一个解决方法。
奇怪的是,当test.num
发生变化时,onChange(of:perform:)
没有运行,但我们仍然可以检测到发布者。因此,我将其拆分为一个单独的视图,当视图接收到新值时,按钮就会更新。
代码:
CommandGroup(after: .newItem) {
TestView(pub: test.$num)
}
struct TestView: View {
let pub: Published<Int>.Publisher
@State private var disabled = true
var body: some View {
Button(action: {}) {
Text("Test menu item")
}
.disabled(disabled)
.onReceive(pub) { new in
disabled = new == 0
}
}
}