This seems like a SwiftUI bug, and I have filed a bug report with Feedback Assistant.
The issue description is in below’s code Text View’s string(there is only one Text View), please read it and try to run the code.
I have also posted another question on stackoverflow before, which seems like a SwiftUI bug too, and that may related to this issue: SwiftUI .keyboardShortcut unexpectedly captured value inside Button's action
Here is the minimal code for reproducing the issue, I run on a new mac app project, macOS version 15.1 Beta (24B5055e), Xcode Version 16.1 beta (16B5001e):
import SwiftUI
@main struct TestDotKeyboardShortcutBugApp: App {
@Environment(\.openWindow) var openWindow
let windowId = "ContentView"
var body: some Scene {
WindowGroup {
Button("Open Window") {
openWindow(id: windowId, value: "")
// openWindow(id: windowId)
}
}
WindowGroup(id: windowId, for: String.self) { _ in
// WindowGroup(id: windowId) {
ContentView()
}
.restorationBehavior(.disabled)
}
}
let key = "Key"
struct ContentView: View {
@AppStorage(key) var appStorageValue: Bool = false
var userDefaultValue: Bool {
UserDefaults.standard.bool(forKey: key)
}
var body: some View {
ScrollViewReader { proxy in
Text("The bug:\nafter switching the value of below Toggle one time, and then press 'a', different values will be printed on the console,\nbut if you click the 'print value' button, same values will be printed.\nHowever, comment out line 9 & 13, then uncomment line 10 & 14, the issue will be gone.")
.padding()
Button("print value") {
print("appStorageValue: \(appStorageValue), userDefaultValue: \(userDefaultValue)")
}
.keyboardShortcut("a", modifiers: [])
Toggle(isOn: $appStorageValue) {
Text("toggle appStorageValue")
}
}
}
}
Is this a SwiftUI bug? If it is, any workaround?
This seems like a SwiftUI bug, and I have filed a bug report with Feedback Assistant.
The issue description is in below’s code Text View’s string(there is only one Text View), please read it and try to run the code.
I have also posted another question on stackoverflow before, which seems like a SwiftUI bug too, and that may related to this issue: SwiftUI .keyboardShortcut unexpectedly captured value inside Button's action
Here is the minimal code for reproducing the issue, I run on a new mac app project, macOS version 15.1 Beta (24B5055e), Xcode Version 16.1 beta (16B5001e):
import SwiftUI
@main struct TestDotKeyboardShortcutBugApp: App {
@Environment(\.openWindow) var openWindow
let windowId = "ContentView"
var body: some Scene {
WindowGroup {
Button("Open Window") {
openWindow(id: windowId, value: "")
// openWindow(id: windowId)
}
}
WindowGroup(id: windowId, for: String.self) { _ in
// WindowGroup(id: windowId) {
ContentView()
}
.restorationBehavior(.disabled)
}
}
let key = "Key"
struct ContentView: View {
@AppStorage(key) var appStorageValue: Bool = false
var userDefaultValue: Bool {
UserDefaults.standard.bool(forKey: key)
}
var body: some View {
ScrollViewReader { proxy in
Text("The bug:\nafter switching the value of below Toggle one time, and then press 'a', different values will be printed on the console,\nbut if you click the 'print value' button, same values will be printed.\nHowever, comment out line 9 & 13, then uncomment line 10 & 14, the issue will be gone.")
.padding()
Button("print value") {
print("appStorageValue: \(appStorageValue), userDefaultValue: \(userDefaultValue)")
}
.keyboardShortcut("a", modifiers: [])
Toggle(isOn: $appStorageValue) {
Text("toggle appStorageValue")
}
}
}
}
Is this a SwiftUI bug? If it is, any workaround?
Share Improve this question edited Jan 23 at 14:07 Jay Tang asked Jan 20 at 4:21 Jay TangJay Tang 156 bronze badges 3 |1 Answer
Reset to default 1View identity is an important concept, which I don't fully understand at times. There are various articles on this, including one at: SwiftUI id.
I sometimes think of it as refreshing the View when nothing else
triggers a change. The appStorageValue
changes in the
Toggle
, but the View already knows about this, and the
side effect print
does not contribute to the view.
Example code that works for me on MacOS 15.3.
@main struct TestDotKeyboardShortcutBugApp: App {
@Environment(\.openWindow) var openWindow
let windowId = "ContentView"
var body: some Scene {
WindowGroup {
Button("Open Window") {
openWindow(id: windowId, value: "")
}
}
WindowGroup(id: windowId, for: String.self) { _ in
ContentView()
}
.restorationBehavior(.disabled)
}
}
struct ContentView: View {
@State private var id = UUID()
@AppStorage("Key") var appStorageValue: Bool = false
var userDefaultValue: Bool {
UserDefaults.standard.bool(forKey: "Key")
}
var body: some View {
Group {
Text("The bug:\nafter switching the value of below Toggle one time, and then press 'a', different values will be printed on the console,\nbut if you click the 'print value' button, same values will be printed.\nHowever, comment out line 9 & 13, then uncomment line 10 & 14, the issue will be gone.")
.padding()
Button("print value") {
print("appStorageValue: \(appStorageValue), userDefaultValue: \(userDefaultValue)")
}
.keyboardShortcut("a", modifiers: [])
Toggle(isOn: $appStorageValue) {
Text("toggle appStorageValue")
}
.onChange(of: appStorageValue) {
id = UUID()
}
}
.id(id)
}
}
.id(UUID())
to yourScrollViewReader
(which probably should be aVStack
orGroup
) then everything works for me on MacOS 15.3. – workingdog support Ukraine Commented Jan 20 at 6:20.id(UUID())
did "fix" this issue and the issue in another question I mentioned too. How do you come up with that "fix"? Did I miss some important concept of SwiftUI? – Jay Tang Commented Jan 23 at 14:22