Fix for freeze in `MenuBarExtra` and `NavigationStack` (#158)
This commit is contained in:
parent
46dfe48645
commit
2dad0e446e
|
@ -6,14 +6,18 @@ extension Defaults {
|
||||||
final class Observable<Value: Serializable>: ObservableObject {
|
final class Observable<Value: Serializable>: ObservableObject {
|
||||||
private var cancellable: AnyCancellable?
|
private var cancellable: AnyCancellable?
|
||||||
private var task: Task<Void, Never>?
|
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 {
|
var value: Value {
|
||||||
get { Defaults[key] }
|
get { Defaults[key] }
|
||||||
set {
|
set {
|
||||||
objectWillChange.send()
|
|
||||||
Defaults[key] = newValue
|
Defaults[key] = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,10 +25,20 @@ extension Defaults {
|
||||||
init(_ key: Key<Value>) {
|
init(_ key: Key<Value>) {
|
||||||
self.key = key
|
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.
|
// 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, *) {
|
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.
|
// 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) {
|
for await _ in Defaults.updates(key) {
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
@ -34,7 +48,7 @@ extension Defaults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.cancellable = Defaults.publisher(key, options: [.prior])
|
cancellable = Defaults.publisher(key, options: [.prior])
|
||||||
.sink { [weak self] change in
|
.sink { [weak self] change in
|
||||||
guard change.isPrior else {
|
guard change.isPrior else {
|
||||||
return
|
return
|
||||||
|
@ -47,10 +61,6 @@ extension Defaults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
|
||||||
task?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset the key back to its default value.
|
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>
|
private let key: Defaults.Key<Value>
|
||||||
|
|
||||||
// Intentionally using `@ObservedObjected` over `@StateObject` so that the key can be dynamically changed.
|
@StateObject private var observable: Defaults.Observable<Value>
|
||||||
@ObservedObject 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`.
|
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>) {
|
public init(_ key: Defaults.Key<Value>) {
|
||||||
self.key = key
|
self.key = key
|
||||||
self.observable = .init(key)
|
self._observable = .init(wrappedValue: .init(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
public var wrappedValue: Value {
|
public var wrappedValue: Value {
|
||||||
|
@ -122,6 +131,7 @@ public struct Default<Value: Defaults.Serializable>: DynamicProperty {
|
||||||
public var publisher: Publisher { Defaults.publisher(key) }
|
public var publisher: Publisher { Defaults.publisher(key) }
|
||||||
|
|
||||||
public mutating func update() {
|
public mutating func update() {
|
||||||
|
observable.key = key
|
||||||
_observable.update()
|
_observable.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue