最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Weird SwiftUI bug, regarding .keyboardShortcut modifier and @AppStorage - Stack Overflow

programmeradmin3浏览0评论

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
  • I think it is to do with how the View is refreshed. For example, if you add .id(UUID()) to your ScrollViewReader (which probably should be a VStack or Group) then everything works for me on MacOS 15.3. – workingdog support Ukraine Commented Jan 20 at 6:20
  • 1 Note, you have posted some code but you don't ask a question. Do you want to "fix" or workaround this issue (easy to do) or simply present a bug. – workingdog support Ukraine Commented Jan 20 at 8:28
  • @workingdogsupportUkraine Hey, thanks, adding .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
Add a comment  | 

1 Answer 1

Reset to default 1

View 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)
     }
 }
 
发布评论

评论列表(0)

  1. 暂无评论