Fix for freeze in `MenuBarExtra` and `NavigationStack` (#158)
This commit is contained in:
parent
46dfe48645
commit
2dad0e446e
|
@ -6,25 +6,39 @@ extension Defaults {
|
|||
final class Observable<Value: Serializable>: ObservableObject {
|
||||
private var cancellable: AnyCancellable?
|
||||
private var task: Task<Void, Never>?
|
||||
private let key: Defaults.Key<Value>
|
||||
|
||||
let objectWillChange = ObservableObjectPublisher()
|
||||
|
||||
var key: Defaults.Key<Value> {
|
||||
didSet {
|
||||
if key != oldValue {
|
||||
observe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var value: Value {
|
||||
get { Defaults[key] }
|
||||
set {
|
||||
objectWillChange.send()
|
||||
Defaults[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
init(_ key: Key<Value>) {
|
||||
self.key = key
|
||||
|
||||
|
||||
observe()
|
||||
}
|
||||
|
||||
deinit {
|
||||
task?.cancel()
|
||||
}
|
||||
|
||||
func observe() {
|
||||
// We only use this on the latest OSes (as of adding this) since the backdeploy library has a lot of bugs.
|
||||
if #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) {
|
||||
task?.cancel()
|
||||
|
||||
// The `@MainActor` is important as the `.send()` method doesn't inherit the `@MainActor` from the class.
|
||||
self.task = .detached(priority: .userInitiated) { @MainActor [weak self] in
|
||||
task = .detached(priority: .userInitiated) { @MainActor [weak self, key] in
|
||||
for await _ in Defaults.updates(key) {
|
||||
guard let self else {
|
||||
return
|
||||
|
@ -34,7 +48,7 @@ extension Defaults {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
self.cancellable = Defaults.publisher(key, options: [.prior])
|
||||
cancellable = Defaults.publisher(key, options: [.prior])
|
||||
.sink { [weak self] change in
|
||||
guard change.isPrior else {
|
||||
return
|
||||
|
@ -47,10 +61,6 @@ extension Defaults {
|
|||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
task?.cancel()
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the key back to its default value.
|
||||
*/
|
||||
|
@ -71,8 +81,7 @@ public struct Default<Value: Defaults.Serializable>: DynamicProperty {
|
|||
|
||||
private let key: Defaults.Key<Value>
|
||||
|
||||
// Intentionally using `@ObservedObjected` over `@StateObject` so that the key can be dynamically changed.
|
||||
@ObservedObject private var observable: Defaults.Observable<Value>
|
||||
@StateObject private var observable: Defaults.Observable<Value>
|
||||
|
||||
/**
|
||||
Get/set a `Defaults` item and also have the view be updated when the value changes. This is similar to `@State`.
|
||||
|
@ -99,7 +108,7 @@ public struct Default<Value: Defaults.Serializable>: DynamicProperty {
|
|||
*/
|
||||
public init(_ key: Defaults.Key<Value>) {
|
||||
self.key = key
|
||||
self.observable = .init(key)
|
||||
self._observable = .init(wrappedValue: .init(key))
|
||||
}
|
||||
|
||||
public var wrappedValue: Value {
|
||||
|
@ -122,6 +131,7 @@ public struct Default<Value: Defaults.Serializable>: DynamicProperty {
|
|||
public var publisher: Publisher { Defaults.publisher(key) }
|
||||
|
||||
public mutating func update() {
|
||||
observable.key = key
|
||||
_observable.update()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue