-
-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MenuBarExtra freezes in a state loop when using Defaults #144
Comments
This is a SwiftUI bug. You can reproduce it without Defaults too: final class AppState: ObservableObject {
@Published var isInserted = true
}
@main
struct AppMain: App {
@StateObject private var appState = AppState()
var body: some Scene {
MenuBarExtra(isInserted: $appState.isInserted) {
Text("A")
} label: {
Text("A")
}
}
} The workaround is to use final class AppState: ObservableObject {
@Published var isInserted = true
}
@main
struct AppMain: App {
@StateObject private var appState = AppState()
var body: some Scene {
MenuBarExtra(isInserted: .constant(appState.isInserted)) {
Text("A")
} label: {
Text("A")
}
}
} |
@sindresorhus Thanks for the prompt reply. I have a few follow up questions if you don't mind me asking. I may be misunderstanding how Also, how does @AppStorage("showMenuBarIcon") private var showMenubarIcon = true
var menuBar: some Scene {
MenuBarExtra("test", systemImage: "plus", isInserted: $showMenubarIcon) {
// ... I still think its a bug in Defaults as it doesn't behave as you'd expect, or as is documented. Especially for people perhaps migrating from |
It means you won't be notified if the user Command-drags the menu bar item out of the menu bar, yes. So it depends on your use-case.
I guess it doesn't use
It is not a bug in Defaults, as I have demonstrated. I do agree it would be nice to work around it, but I'm not sure of any workaround as |
Using |
I can keep this issue open for discoverability until Apple fixes the issue. |
@sindresorhus Thanks again for the prompt reply, and the knowledge share!
Hmmm. I mean my current use case is reacting to the user Default preference on whether they'd like the menu bar status icon to be visible. So something like: @Default(.menuBarShowIcon) private var menuBarShowIcon
var menuBar: some Scene {
MenuBarExtra("test", systemImage: "plus", isInserted: $menuBarShowIcon) {
// ... Which based on what you demonstrated needs to be replaced with the following to work correctly: @Default(.menuBarShowIcon) private var menuBarShowIcon
var menuBar: some Scene {
MenuBarExtra("test", systemImage: "plus", isInserted: .constant($menuBarShowIcon)) {
// ...
Good idea, thank you for the suggestion. If the above doesn't work as intended, I'll use this approach instead! 🙌
Ah. I see now, well thats a pain. Thanks for explaining. At the behest of Apple once again!
Thanks, its a shame Apple doesn't have a public issue tracker for this stuff for this issue to then be linked against. This one may remain open for a while otherwise 😬 |
@sindresorhus, Isn't this issue caused by the use of
This is what's happening in this case. var value: Value {
get { Defaults[key] }
set {
// objectWillChange.send() <-- removed
Defaults[key] = newValue
}
} This fixes the issue, and also issue #146. As for dynamically changing the key of the wrapper, the watched key could be updated in the ObservableObject, instead of in the property wrapper. |
The SwiftUI bug is triggered by that, yes, but using
That is only advisory and meant to prevent situations where your view model keeps getting re-initiated, but that's not a problem in this case.
It's not strictly needed, but it does make it guaranteed the change is reflected in the current view loop and not the next one, which could improve perceived performance.
I'm ok with doing that. We can just target the macOS 11 and iOS 14 in Defaults. Pull request welcome. |
It appears someone published a similar issue to this, but didn't respond when macOS 13 was retail released: #106
The example remains the same from that issue - in fact that issue is still directly happening exactly as described. With the issue Wouter01 was having being nearly identical in setup to mine.
Attempting to use
@Default
will break the app and lock it into a state loop:However to provide more insights into the issue, here is the exact error message being given:
This will hang the app as soon as the main window loads and is pulled into focus, with the app entering a state loop, with the debug console being spammed with the above error message.
With Xcode's debugger pointing at this line of code as the culprit:
https://github.com/sindresorhus/Defaults/blob/main/Sources/Defaults/SwiftUI.swift#L16
With a screenshot for reference within Xcode:
Although knowing Xcode, that probably isn't the source of the issue...
I'm not really sure how to debug this, so I can't really provide any insights beyond surfacing the problem I'm afraid, although I'll try to assist the best I can.
The text was updated successfully, but these errors were encountered: