From 110f2d2b9e5e1b137bf62ee2cfff039443dd6e1b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Fri, 28 Aug 2020 22:38:56 +0200 Subject: [PATCH] Various improvements --- Defaults.xcodeproj/project.pbxproj | 20 +- Sources/Defaults/Defaults.swift | 11 +- Sources/Defaults/Observation+Combine.swift | 4 +- Sources/Defaults/Observation.swift | 92 +- Sources/Defaults/Reset.swift | 1001 +---------------- Sources/Defaults/SwiftUI.swift | 2 - .../Defaults/{util.swift => Utilities.swift} | 0 Tests/DefaultsTests/DefaultsTests.swift | 59 +- readme.md | 45 +- 9 files changed, 119 insertions(+), 1115 deletions(-) rename Sources/Defaults/{util.swift => Utilities.swift} (100%) diff --git a/Defaults.xcodeproj/project.pbxproj b/Defaults.xcodeproj/project.pbxproj index ca2e543..60c4851 100644 --- a/Defaults.xcodeproj/project.pbxproj +++ b/Defaults.xcodeproj/project.pbxproj @@ -33,14 +33,14 @@ E38C9F28244ADA2F00A6737A /* SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38C9F26244ADA2F00A6737A /* SwiftUI.swift */; }; E38C9F29244ADA2F00A6737A /* SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38C9F26244ADA2F00A6737A /* SwiftUI.swift */; }; E38C9F2A244ADA2F00A6737A /* SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38C9F26244ADA2F00A6737A /* SwiftUI.swift */; }; - E3EB3E33216505920033B089 /* util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* util.swift */; }; + E3EB3E33216505920033B089 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* Utilities.swift */; }; E3EB3E35216507AE0033B089 /* Observation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E34216507AE0033B089 /* Observation.swift */; }; E3EB3E36216507B50033B089 /* Observation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E34216507AE0033B089 /* Observation.swift */; }; E3EB3E37216507B50033B089 /* Observation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E34216507AE0033B089 /* Observation.swift */; }; E3EB3E38216507B60033B089 /* Observation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E34216507AE0033B089 /* Observation.swift */; }; - E3EB3E39216507C30033B089 /* util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* util.swift */; }; - E3EB3E3A216507C40033B089 /* util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* util.swift */; }; - E3EB3E3B216507C40033B089 /* util.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* util.swift */; }; + E3EB3E39216507C30033B089 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* Utilities.swift */; }; + E3EB3E3A216507C40033B089 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* Utilities.swift */; }; + E3EB3E3B216507C40033B089 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3EB3E32216505920033B089 /* Utilities.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -84,7 +84,7 @@ E339B3B22449ED2000E7A40A /* Reset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Reset.swift; sourceTree = ""; usesTabs = 1; }; E339B3B72449F10D00E7A40A /* UserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = UserDefaults.swift; sourceTree = ""; usesTabs = 1; }; E38C9F26244ADA2F00A6737A /* SwiftUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SwiftUI.swift; sourceTree = ""; usesTabs = 1; }; - E3EB3E32216505920033B089 /* util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = util.swift; sourceTree = ""; usesTabs = 1; }; + E3EB3E32216505920033B089 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Utilities.swift; sourceTree = ""; usesTabs = 1; }; E3EB3E34216507AE0033B089 /* Observation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Observation.swift; sourceTree = ""; usesTabs = 1; }; /* End PBXFileReference section */ @@ -221,7 +221,7 @@ E3EB3E34216507AE0033B089 /* Observation.swift */, E286D0C623B8D51100570D1E /* Observation+Combine.swift */, E38C9F26244ADA2F00A6737A /* SwiftUI.swift */, - E3EB3E32216505920033B089 /* util.swift */, + E3EB3E32216505920033B089 /* Utilities.swift */, ); path = Defaults; sourceTree = ""; @@ -512,7 +512,7 @@ 8933C7851EB5B820000D00A4 /* Defaults.swift in Sources */, E339B3B92449F10D00E7A40A /* UserDefaults.swift in Sources */, E3EB3E35216507AE0033B089 /* Observation.swift in Sources */, - E3EB3E33216505920033B089 /* util.swift in Sources */, + E3EB3E33216505920033B089 /* Utilities.swift in Sources */, E339B3B42449ED2000E7A40A /* Reset.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -531,7 +531,7 @@ files = ( E286D0CA23B8D54E00570D1E /* Observation+Combine.swift in Sources */, E38C9F2A244ADA2F00A6737A /* SwiftUI.swift in Sources */, - E3EB3E3A216507C40033B089 /* util.swift in Sources */, + E3EB3E3A216507C40033B089 /* Utilities.swift in Sources */, E339B3BB2449F10D00E7A40A /* UserDefaults.swift in Sources */, E3EB3E37216507B50033B089 /* Observation.swift in Sources */, 8933C7871EB5B820000D00A4 /* Defaults.swift in Sources */, @@ -545,7 +545,7 @@ files = ( E286D0C923B8D54D00570D1E /* Observation+Combine.swift in Sources */, E38C9F29244ADA2F00A6737A /* SwiftUI.swift in Sources */, - E3EB3E3B216507C40033B089 /* util.swift in Sources */, + E3EB3E3B216507C40033B089 /* Utilities.swift in Sources */, E339B3BA2449F10D00E7A40A /* UserDefaults.swift in Sources */, E3EB3E38216507B60033B089 /* Observation.swift in Sources */, 8933C7881EB5B820000D00A4 /* Defaults.swift in Sources */, @@ -559,7 +559,7 @@ files = ( E286D0C723B8D51100570D1E /* Observation+Combine.swift in Sources */, E38C9F27244ADA2F00A6737A /* SwiftUI.swift in Sources */, - E3EB3E39216507C30033B089 /* util.swift in Sources */, + E3EB3E39216507C30033B089 /* Utilities.swift in Sources */, E339B3B82449F10D00E7A40A /* UserDefaults.swift in Sources */, E3EB3E36216507B50033B089 /* Observation.swift in Sources */, 8933C7861EB5B820000D00A4 /* Defaults.swift in Sources */, diff --git a/Sources/Defaults/Defaults.swift b/Sources/Defaults/Defaults.swift index 4ae8966..227c9bb 100644 --- a/Sources/Defaults/Defaults.swift +++ b/Sources/Defaults/Defaults.swift @@ -1,7 +1,7 @@ // MIT License © Sindre Sorhus import Foundation -public protocol DefaultsBaseKey: Defaults.Keys { +public protocol DefaultsBaseKey: Defaults.AnyKey { var name: String { get } var suite: UserDefaults { get } } @@ -15,7 +15,8 @@ extension DefaultsBaseKey { public enum Defaults { public typealias BaseKey = DefaultsBaseKey - + public typealias AnyKey = Keys + public class Keys: BaseKey { public typealias Key = Defaults.Key @@ -34,7 +35,7 @@ public enum Defaults { } } - public final class Key: Keys { + public final class Key: AnyKey { public let defaultValue: Value /// Create a defaults key. @@ -58,7 +59,7 @@ public enum Defaults { } @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public final class NSSecureCodingKey: Keys { + public final class NSSecureCodingKey: AnyKey { public let defaultValue: Value /// Create a defaults key. @@ -82,7 +83,7 @@ public enum Defaults { } @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public final class NSSecureCodingOptionalKey: Keys { + public final class NSSecureCodingOptionalKey: AnyKey { /// Create an optional defaults key. public init(_ key: String, suite: UserDefaults = .standard) { super.init(name: key, suite: suite) diff --git a/Sources/Defaults/Observation+Combine.swift b/Sources/Defaults/Observation+Combine.swift index d036ced..201c870 100644 --- a/Sources/Defaults/Observation+Combine.swift +++ b/Sources/Defaults/Observation+Combine.swift @@ -1,5 +1,4 @@ #if canImport(Combine) - import Foundation import Combine @@ -133,7 +132,7 @@ extension Defaults { */ @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, iOSApplicationExtension 13.0, macOSApplicationExtension 10.15, tvOSApplicationExtension 13.0, watchOSApplicationExtension 6.0, *) public static func publisher( - keys: Keys..., + keys: AnyKey..., options: ObservationOptions = [.initial] ) -> AnyPublisher { let initial = Empty(completeImmediately: false).eraseToAnyPublisher() @@ -150,5 +149,4 @@ extension Defaults { return combinedPublisher } } - #endif diff --git a/Sources/Defaults/Observation.swift b/Sources/Defaults/Observation.swift index 0bcb033..f0ef82a 100644 --- a/Sources/Defaults/Observation.swift +++ b/Sources/Defaults/Observation.swift @@ -140,39 +140,39 @@ extension Defaults { self.newValue = deserialize(change.newValue, to: Value.self) } } - - private static var preventPropagationThreadDictKey: String { + + private static var preventPropagationThreadDictionaryKey: String { "\(type(of: Observation.self))_threadUpdatingValuesFlag" } - + /** - Execute block without triggering events of changes made at defaults keys. - - Example: + Execute the closure without triggering change events. + + Any `Defaults` key changes made within the closure will not propagate to `Defaults` event listeners (`Defaults.observe()` and `Defaults.publisher()`). This can be useful to prevent infinite recursion when you want to change a key in the callback listening to changes for the same key. + + - Note: This only works with `Defaults.observe()` and `Defaults.publisher()`. User-made KVO will not be affected. + ``` let observer = Defaults.observe(keys: .key1, .key2) { // … + Defaults.withoutPropagation { - // update some value at .key1 - // this will not be propagated + // Update `.key1` without propagating the change to listeners. Defaults[.key1] = 11 } - // this will be propagated + + // This will be propagated. Defaults[.someKey] = true } ``` - - This only works with defaults `observe` or `publisher`. User made KVO will not be affected. */ - public static func withoutPropagation(block: () -> Void) { + public static func withoutPropagation(_ closure: () -> Void) { // How does it work? - // KVO observation callbacks are executed right after change is made, - // and run on the same thread as the caller. So it works by storing a flag in current - // thread's dictionary, which is then evaluated in `observeValue` callback - - let key = preventPropagationThreadDictKey + // KVO observation callbacks are executed right after a change is made, and run on the same thread as the caller. So it works by storing a flag in the current thread's dictionary, which is then evaluated in the callback. + + let key = preventPropagationThreadDictionaryKey Thread.current.threadDictionary[key] = true - block() + closure() Thread.current.threadDictionary[key] = false } @@ -235,8 +235,8 @@ extension Defaults { else { return } - - let key = preventPropagationThreadDictKey + + let key = preventPropagationThreadDictionaryKey let updatingValuesFlag = (Thread.current.threadDictionary[key] as? Bool) ?? false guard !updatingValuesFlag else { return @@ -245,66 +245,66 @@ extension Defaults { callback(BaseChange(change: change)) } } - + private final class CompositeUserDefaultsKeyObservation: NSObject, Observation { private static var observationContext = 0 - + private final class SuiteKeyPair { weak var suite: UserDefaults? let key: String - + init(suite: UserDefaults, key: String) { self.suite = suite self.key = key } } - + private var observables: [SuiteKeyPair] - private var lifetimeAssociation: LifetimeAssociation? = nil + private var lifetimeAssociation: LifetimeAssociation? private let callback: UserDefaultsKeyObservation.Callback - + init(observables: [(suite: UserDefaults, key: String)], callback: @escaping UserDefaultsKeyObservation.Callback) { self.observables = observables.map { SuiteKeyPair(suite: $0.suite, key: $0.key) } self.callback = callback super.init() } - + deinit { invalidate() } - + public func start(options: ObservationOptions) { for observable in observables { observable.suite?.addObserver( self, forKeyPath: observable.key, options: options.toNSKeyValueObservingOptions, - context: &type(of: self).observationContext + context: &Self.observationContext ) } } - + public func invalidate() { for observable in observables { - observable.suite?.removeObserver(self, forKeyPath: observable.key, context: &type(of: self).observationContext) + observable.suite?.removeObserver(self, forKeyPath: observable.key, context: &Self.observationContext) observable.suite = nil } lifetimeAssociation?.cancel() } - + public func tieToLifetime(of weaklyHeldObject: AnyObject) -> Self { lifetimeAssociation = LifetimeAssociation(of: self, with: weaklyHeldObject, deinitHandler: { [weak self] in self?.invalidate() }) - + return self } public func removeLifetimeTie() { lifetimeAssociation?.cancel() } - + // swiftlint:disable:next block_based_kvo override func observeValue( forKeyPath keyPath: String?, @@ -313,29 +313,29 @@ extension Defaults { context: UnsafeMutableRawPointer? ) { guard - context == &type(of: self).observationContext + context == &Self.observationContext else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } - + guard object is UserDefaults, let change = change else { return } - - let key = preventPropagationThreadDictKey + + let key = preventPropagationThreadDictionaryKey let updatingValuesFlag = (Thread.current.threadDictionary[key] as? Bool) ?? false if updatingValuesFlag { return } - + callback(BaseChange(change: change)) } } - + /** Observe a defaults key. @@ -399,10 +399,10 @@ extension Defaults { observation.start(options: options) return observation } - + /** - Observe multiple keys of any type, but without specific information about changes. - + Observe multiple keys of any type, but without any information about the changes. + ``` extension Defaults.Keys { static let setting1 = Key("setting1", default: false) @@ -410,12 +410,12 @@ extension Defaults { } let observer = Defaults.observe(keys: .setting1, .setting2) { - //... + // … } ``` */ public static func observe( - keys: Keys..., + keys: AnyKey..., options: ObservationOptions = [.initial], handler: @escaping () -> Void ) -> Observation { @@ -426,7 +426,7 @@ extension Defaults { handler() } compositeObservation.start(options: options) - + return compositeObservation } } diff --git a/Sources/Defaults/Reset.swift b/Sources/Defaults/Reset.swift index a81676c..d86ddcd 100644 --- a/Sources/Defaults/Reset.swift +++ b/Sources/Defaults/Reset.swift @@ -1,19 +1,5 @@ import Foundation -/* -TODO: When Swift gets support for static key paths, all of this could be simplified to just: - -``` -extension Defaults { - public static func reset(_ keys: KeyPath...) { - for key in keys { - Keys[keyPath: key].reset() - } - } -} -``` -*/ - extension Defaults { /** Reset the given string keys back to their default values. @@ -76,10 +62,6 @@ extension Defaults { /** Reset the given keys back to their default values. - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - ``` extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: false) @@ -94,21 +76,13 @@ extension Defaults { //=> false ``` */ - public static func reset< - Value1 - >( - _ key1: Key - ) { - key1.reset() + public static func reset(_ keys: AnyKey...) { + reset(keys) } /** Reset the given keys back to their default values. - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - ``` extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: false) @@ -123,972 +97,9 @@ extension Defaults { //=> false ``` */ - public static func reset< - Value1, - Value2 - >( - _ key1: Key, - _ key2: Key - ) { - key1.reset() - key2.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key - ) { - key1.reset() - key2.reset() - key3.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key, - _ key6: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key, - _ key6: Key, - _ key7: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key, - _ key6: Key, - _ key7: Key, - _ key8: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key, - _ key6: Key, - _ key7: Key, - _ key8: Key, - _ key9: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - - ``` - extension Defaults.Keys { - static let isUnicornMode = Key("isUnicornMode", default: false) - } - - Defaults[.isUnicornMode] = true - //=> true - - Defaults.reset(.isUnicornMode) - - Defaults[.isUnicornMode] - //=> false - ``` - */ - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9, - Value10 - >( - _ key1: Key, - _ key2: Key, - _ key3: Key, - _ key4: Key, - _ key5: Key, - _ key6: Key, - _ key7: Key, - _ key8: Key, - _ key9: Key, - _ key10: Key - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - key10.reset() - } -} - -extension Defaults { - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1 - >( - _ key1: NSSecureCodingKey - ) { - key1.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey, - _ key6: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey, - _ key6: NSSecureCodingKey, - _ key7: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey, - _ key6: NSSecureCodingKey, - _ key7: NSSecureCodingKey, - _ key8: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey, - _ key6: NSSecureCodingKey, - _ key7: NSSecureCodingKey, - _ key8: NSSecureCodingKey, - _ key9: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9, - Value10 - >( - _ key1: NSSecureCodingKey, - _ key2: NSSecureCodingKey, - _ key3: NSSecureCodingKey, - _ key4: NSSecureCodingKey, - _ key5: NSSecureCodingKey, - _ key6: NSSecureCodingKey, - _ key7: NSSecureCodingKey, - _ key8: NSSecureCodingKey, - _ key9: NSSecureCodingKey, - _ key10: NSSecureCodingKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - key10.reset() - } -} - -extension Defaults { - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1 - >( - _ key1: NSSecureCodingOptionalKey - ) { - key1.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey, - _ key6: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey, - _ key6: NSSecureCodingOptionalKey, - _ key7: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey, - _ key6: NSSecureCodingOptionalKey, - _ key7: NSSecureCodingOptionalKey, - _ key8: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey, - _ key6: NSSecureCodingOptionalKey, - _ key7: NSSecureCodingOptionalKey, - _ key8: NSSecureCodingOptionalKey, - _ key9: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - } - - /** - Reset the given keys back to their default values. - - You can specify up to 10 keys. If you need to specify more, call this method multiple times. - - The 10 limit is a Swift generics limitation. If you really want, you could specify more overloads. - */ - @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) - public static func reset< - Value1, - Value2, - Value3, - Value4, - Value5, - Value6, - Value7, - Value8, - Value9, - Value10 - >( - _ key1: NSSecureCodingOptionalKey, - _ key2: NSSecureCodingOptionalKey, - _ key3: NSSecureCodingOptionalKey, - _ key4: NSSecureCodingOptionalKey, - _ key5: NSSecureCodingOptionalKey, - _ key6: NSSecureCodingOptionalKey, - _ key7: NSSecureCodingOptionalKey, - _ key8: NSSecureCodingOptionalKey, - _ key9: NSSecureCodingOptionalKey, - _ key10: NSSecureCodingOptionalKey - ) { - key1.reset() - key2.reset() - key3.reset() - key4.reset() - key5.reset() - key6.reset() - key7.reset() - key8.reset() - key9.reset() - key10.reset() + public static func reset(_ keys: [AnyKey]) { + for key in keys { + key.reset() + } } } diff --git a/Sources/Defaults/SwiftUI.swift b/Sources/Defaults/SwiftUI.swift index 1a83a5d..26f7f0b 100644 --- a/Sources/Defaults/SwiftUI.swift +++ b/Sources/Defaults/SwiftUI.swift @@ -1,5 +1,4 @@ #if canImport(Combine) - import SwiftUI import Combine @@ -111,5 +110,4 @@ public struct Default: DynamicProperty { key.reset() } } - #endif diff --git a/Sources/Defaults/util.swift b/Sources/Defaults/Utilities.swift similarity index 100% rename from Sources/Defaults/util.swift rename to Sources/Defaults/Utilities.swift diff --git a/Tests/DefaultsTests/DefaultsTests.swift b/Tests/DefaultsTests/DefaultsTests.swift index 74dce7a..9d4d442 100644 --- a/Tests/DefaultsTests/DefaultsTests.swift +++ b/Tests/DefaultsTests/DefaultsTests.swift @@ -369,7 +369,7 @@ final class DefaultsTests: XCTestCase { let publisher = Defaults .publisher(key) - .compactMap { $0.newValue } + .map(\.newValue) .eraseToAnyPublisher() .collect(2) @@ -452,12 +452,12 @@ final class DefaultsTests: XCTestCase { waitForExpectations(timeout: 10) } - + func testObserveMultipleKeys() { let key1 = Defaults.Key("observeKey1", default: "x") let key2 = Defaults.Key("observeKey2", default: true) let expect = expectation(description: "Observation closure being called") - + var observation: Defaults.Observation! var counter = 0 observation = Defaults.observe(keys: key1, key2, options: []) { @@ -468,20 +468,20 @@ final class DefaultsTests: XCTestCase { XCTFail() } } - + Defaults[key1] = "y" Defaults[key2] = false observation.invalidate() - + waitForExpectations(timeout: 10) } - + @available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) func testObserveMultipleNSSecureKeys() { let key1 = Defaults.NSSecureCodingKey("observeNSSecureCodingKey1", default: ExamplePersistentHistory(value: "TestValue")) let key2 = Defaults.NSSecureCodingKey("observeNSSecureCodingKey2", default: ExamplePersistentHistory(value: "TestValue")) let expect = expectation(description: "Observation closure being called") - + var observation: Defaults.Observation! var counter = 0 observation = Defaults.observe(keys: key1, key2, options: []) { @@ -492,7 +492,7 @@ final class DefaultsTests: XCTestCase { XCTFail() } } - + Defaults[key1] = ExamplePersistentHistory(value: "NewTestValue1") Defaults[key2] = ExamplePersistentHistory(value: "NewTestValue2") observation.invalidate() @@ -535,7 +535,7 @@ final class DefaultsTests: XCTestCase { waitForExpectations(timeout: 10) } - + func testObservePreventPropagation() { let key1 = Defaults.Key("preventPropagation0", default: nil) let expect = expectation(description: "No infinite recursion") @@ -556,7 +556,7 @@ final class DefaultsTests: XCTestCase { waitForExpectations(timeout: 10) } - + func testObservePreventPropagationMultipleKeys() { let key1 = Defaults.Key("preventPropagation1", default: nil) let key2 = Defaults.Key("preventPropagation2", default: nil) @@ -578,15 +578,12 @@ final class DefaultsTests: XCTestCase { waitForExpectations(timeout: 10) } - - /** - This checks if callback is still being called, if value is changed on second thread, - while initial thread is doing some long lasting task. - */ + + // This checks if the callback is still being called if the value is changed on a second thread while the initial thread is doing some long running task. func testObservePreventPropagationMultipleThreads() { let key1 = Defaults.Key("preventPropagation3", default: nil) let expect = expectation(description: "No infinite recursion") - + var observation: Defaults.Observation! observation = Defaults.observe(key1, options: []) { _ in Defaults.withoutPropagation { @@ -609,10 +606,8 @@ final class DefaultsTests: XCTestCase { waitForExpectations(timeout: 10) } - - /** - Check if propagation prevention works across multiple observations - */ + + // Check if propagation prevention works across multiple observations. func testObservePreventPropagationMultipleObservations() { let key1 = Defaults.Key("preventPropagation4", default: nil) let key2 = Defaults.Key("preventPropagation5", default: nil) @@ -627,14 +622,14 @@ final class DefaultsTests: XCTestCase { } expect.fulfill() } - + Defaults[key1] = false observation1.invalidate() observation2.invalidate() - + waitForExpectations(timeout: 10) } - + @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, iOSApplicationExtension 13.0, macOSApplicationExtension 10.15, tvOSApplicationExtension 13.0, watchOSApplicationExtension 6.0, *) func testObservePreventPropagationCombine() { let key1 = Defaults.Key("preventPropagation6", default: nil) @@ -649,13 +644,13 @@ final class DefaultsTests: XCTestCase { } expect.fulfill() } - + Defaults[key1] = false cancellable.cancel() - + waitForExpectations(timeout: 10) } - + @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, iOSApplicationExtension 13.0, macOSApplicationExtension 10.15, tvOSApplicationExtension 13.0, watchOSApplicationExtension 6.0, *) func testObservePreventPropagationMultipleKeysCombine() { let key1 = Defaults.Key("preventPropagation7", default: nil) @@ -671,18 +666,18 @@ final class DefaultsTests: XCTestCase { } expect.fulfill() } - + Defaults[key2] = false cancellable.cancel() - + waitForExpectations(timeout: 10) } - + @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, iOSApplicationExtension 13.0, macOSApplicationExtension 10.15, tvOSApplicationExtension 13.0, watchOSApplicationExtension 6.0, *) func testObservePreventPropagationModifiersCombine() { let key1 = Defaults.Key("preventPropagation9", default: nil) let expect = expectation(description: "No infinite recursion") - + var wasInside = false var cancellable: AnyCancellable! cancellable = Defaults.publisher(key1, options: []) @@ -697,9 +692,9 @@ final class DefaultsTests: XCTestCase { expect.fulfill() cancellable.cancel() } - + Defaults[key1] = false - + waitForExpectations(timeout: 10) } diff --git a/readme.md b/readme.md index bf468ec..3d10616 100644 --- a/readme.md +++ b/readme.md @@ -239,23 +239,6 @@ Defaults[.isUnicornMode] = true The observation will be valid until `self` is deinitialized. -### Control propagation of change events - -```swift -let observer = Defaults.observe(keys: .key1, .key2) { - // … - Defaults.withoutPropagation { - // update some value at .key1 - // this will not be propagated - Defaults[.key1] = 11 - } - // this will be propagated - Defaults[.someKey] = true -} -``` - -Changes made within `Defaults.withoutPropagation` block, will not be propagated to observation callbacks, and therefore will prevent infinite recursion. - ### Reset keys to their default values ```swift @@ -274,6 +257,24 @@ Defaults[.isUnicornMode] This works for a `Key` with an optional too, which will be reset back to `nil`. +### Control propagation of change events + +Changes made within the `Defaults.withoutPropagation` closure will not be propagated to observation callbacks (`Defaults.observe()` or `Defaults.publisher()`), and therefore could prevent infinite recursion. + +```swift +let observer = Defaults.observe(keys: .key1, .key2) { + // … + + Defaults.withoutPropagation { + // Update `.key1` without propagating the change to listeners. + Defaults[.key1] = 11 + } + + // This will be propagated. + Defaults[.someKey] = true + } +``` + ### It's just `UserDefaults` with sugar This works too: @@ -408,9 +409,9 @@ By default, it will also trigger an initial event on creation. This can be usefu Type: `func` -Observe changes to multiple keys of any type, but without specific information about changes. +Observe multiple keys of any type, but without any information about the changes. -Options same as in `observe` for a single key. +Options are the same as in `.observe(…)` for a single key. #### `Defaults.publisher(_ key:, options:)` @@ -500,11 +501,11 @@ Break the lifetime tie created by `tieToLifetime(of:)`, if one exists. The effects of any call to `tieToLifetime(of:)` are reversed. Note however that if the tied-to object has already died, then the observation is already invalid and this method has no logical effect. -#### `Defaults.withoutPropagation(_ block:)` +#### `Defaults.withoutPropagation(_ closure:)` -Execute block without emitting events of changes made at defaults keys. +Execute the closure without triggering change events. -Changes made within the block will not be propagated to observation callbacks. This only works with defaults `observe` or `publisher`. User made KVO will not be affected. +Any `Defaults` key changes made within the closure will not propagate to `Defaults` event listeners (`Defaults.observe()` and `Defaults.publisher()`). This can be useful to prevent infinite recursion when you want to change a key in the callback listening to changes for the same key. ### `@Default(_ key:)`