Skip to content

Commit 11b6adb

Browse files
Add .publisher() overload that accepts an array of keys (#148)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 957d807 commit 11b6adb

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

Sources/Defaults/Observation+Combine.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ extension Defaults {
102102
- Warning: This method exists for backwards compatibility and will be deprecated sometime in the future. Use ``Defaults/updates(_:initial:)-9eh8`` instead.
103103
*/
104104
public static func publisher(
105-
keys: _AnyKey...,
105+
keys: [_AnyKey],
106106
options: ObservationOptions = [.initial]
107107
) -> AnyPublisher<Void, Never> {
108108
let initial = Empty<Void, Never>(completeImmediately: false).eraseToAnyPublisher()
@@ -118,4 +118,16 @@ extension Defaults {
118118
combined.merge(with: keyPublisher).eraseToAnyPublisher()
119119
}
120120
}
121+
122+
/**
123+
Publisher for multiple `Key<T>` observation, but without specific information about changes.
124+
125+
- Warning: This method exists for backwards compatibility and will be deprecated sometime in the future. Use ``Defaults/updates(_:initial:)-9eh8`` instead.
126+
*/
127+
public static func publisher(
128+
keys: _AnyKey...,
129+
options: ObservationOptions = [.initial]
130+
) -> AnyPublisher<Void, Never> {
131+
publisher(keys: keys, options: options)
132+
}
121133
}

Sources/Defaults/Observation.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ extension Defaults {
125125
private weak var object: UserDefaults?
126126
private let key: String
127127
private let callback: Callback
128+
private var isObserving = false
128129

129130
init(object: UserDefaults, key: String, callback: @escaping Callback) {
130131
self.object = object
@@ -138,10 +139,15 @@ extension Defaults {
138139

139140
func start(options: ObservationOptions) {
140141
object?.addObserver(self, forKeyPath: key, options: options.toNSKeyValueObservingOptions, context: nil)
142+
isObserving = true
141143
}
142144

143145
func invalidate() {
144-
object?.removeObserver(self, forKeyPath: key, context: nil)
146+
if isObserving {
147+
object?.removeObserver(self, forKeyPath: key, context: nil)
148+
isObserving = false
149+
}
150+
145151
object = nil
146152
lifetimeAssociation?.cancel()
147153
}

Tests/DefaultsTests/DefaultsTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,23 @@ final class DefaultsTests: XCTestCase {
733733
waitForExpectations(timeout: 10)
734734
}
735735

736+
func testImmediatelyFinishingMultiplePublisherCombine() {
737+
let key1 = Defaults.Key<Bool>("observeKey1", default: false)
738+
let key2 = Defaults.Key<String>("observeKey2", default: "🦄")
739+
let expect = expectation(description: "Observation closure being called without crashing")
740+
741+
let cancellable = Defaults
742+
.publisher(keys: [key1, key2], options: [.initial])
743+
.first()
744+
.sink { _ in
745+
expect.fulfill()
746+
}
747+
748+
cancellable.cancel()
749+
750+
waitForExpectations(timeout: 10)
751+
}
752+
736753
func testKeyEquatable() {
737754
XCTAssertEqual(Defaults.Key<Bool>("equatableKeyTest", default: false), Defaults.Key<Bool>("equatableKeyTest", default: false))
738755
}

0 commit comments

Comments
 (0)