diff --git a/Sources/Defaults/Defaults+Bridge.swift b/Sources/Defaults/Defaults+Bridge.swift index b1da6fc..c38a36b 100644 --- a/Sources/Defaults/Defaults+Bridge.swift +++ b/Sources/Defaults/Defaults+Bridge.swift @@ -428,7 +428,7 @@ extension Defaults { } extension Defaults { - public struct AnyBridge: Defaults.Bridge, Sendable { + public struct AnyBridge: Bridge, Sendable { public typealias Value = Defaults.AnySerializable public typealias Serializable = Any diff --git a/Sources/Defaults/Defaults.swift b/Sources/Defaults/Defaults.swift index 79aefa3..54c0114 100644 --- a/Sources/Defaults/Defaults.swift +++ b/Sources/Defaults/Defaults.swift @@ -209,9 +209,9 @@ extension Defaults.Key { extension Defaults.Key where Value: Equatable { /** - Check whether the stored value is the default value. + Indicates whether the value is the same as the default value. */ - public var isDefaultValue: Bool { self._isDefaultValue } + public var isDefaultValue: Bool { suite[self] == defaultValue } } extension Defaults { diff --git a/Sources/Defaults/Observation.swift b/Sources/Defaults/Observation.swift index 89375cd..b33723a 100644 --- a/Sources/Defaults/Observation.swift +++ b/Sources/Defaults/Observation.swift @@ -287,11 +287,16 @@ extension Defaults { } func start(options: ObservationOptions) { - observations.forEach { $0.start(options: options) } + for observation in observations { + observation.start(options: options) + } } func invalidate() { - observations.forEach { $0.invalidate() } + for observation in observations { + observation.invalidate() + } + lifetimeAssociation?.cancel() } @@ -305,7 +310,7 @@ extension Defaults { } func remove(key: Defaults._AnyKey) { - guard let observation = observations.remove(DefaultsObservation(key: key, self.callback)) else { + guard let observation = observations.remove(DefaultsObservation(key: key, callback)) else { return } diff --git a/Sources/Defaults/SwiftUI.swift b/Sources/Defaults/SwiftUI.swift index cf3e76c..d1d8488 100644 --- a/Sources/Defaults/SwiftUI.swift +++ b/Sources/Defaults/SwiftUI.swift @@ -32,7 +32,7 @@ extension Defaults { task?.cancel() } - func observe() { + private 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, visionOS 1.0, *) { task?.cancel() @@ -44,7 +44,7 @@ extension Defaults { return } - self.objectWillChange.send() + objectWillChange.send() } } } else { @@ -221,12 +221,26 @@ extension Defaults { } extension Defaults.Toggle { - public init(_ title: some StringProtocol, key: Defaults.Key) { + public init( + _ title: some StringProtocol, + key: Defaults.Key + ) { self.label = { Text(title) } self.observable = .init(key) } } +extension Defaults.Toggle> { + public init( + _ title: some StringProtocol, + systemImage: String, + key: Defaults.Key + ) { + self.label = { Label(title, systemImage: systemImage) } + self.observable = .init(key) + } +} + extension Defaults.Toggle { /** Do something when the value changes to a different value. diff --git a/Tests/DefaultsTests/DefaultsTests.swift b/Tests/DefaultsTests/DefaultsTests.swift index 091b47b..8775016 100644 --- a/Tests/DefaultsTests/DefaultsTests.swift +++ b/Tests/DefaultsTests/DefaultsTests.swift @@ -771,7 +771,7 @@ final class DefaultsTests: XCTestCase { async let waiter = Defaults.updates(key, initial: false).first { $0 } - try? await Task.sleep(seconds: 0.1) + try? await Task.sleep(for: .seconds(0.1)) Defaults[key] = true @@ -798,7 +798,7 @@ final class DefaultsTests: XCTestCase { } }() - try? await Task.sleep(seconds: 0.1) + try? await Task.sleep(for: .seconds(0.1)) Defaults[key1] = true Defaults[key2] = true @@ -820,10 +820,4 @@ actor Counter { } } -// TODO: Remove when testing on macOS 13. -extension Task { - static func sleep(seconds: TimeInterval) async throws { - try await sleep(nanoseconds: UInt64(seconds * Double(NSEC_PER_SEC))) - } -} // swiftlint:enable discouraged_optional_boolean diff --git a/readme.md b/readme.md index 1052269..3dafd90 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ Store key-value pairs persistently across launches of your app. It uses `UserDefaults` underneath but exposes a type-safe facade with lots of nice conveniences. -It's used in production by [all my apps](https://sindresorhus.com/apps) (1 million+ users). +It's used in production by [all my apps](https://sindresorhus.com/apps) (4 million+ users). ## Highlights