From 3275717838bdaab27df2357b071bff4d2b44adfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20R=C4=85czy?= Date: Sun, 5 Apr 2020 16:56:59 +0200 Subject: [PATCH] Fix crash in the Combine API (#39) --- Sources/Defaults/Observation+Combine.swift | 8 +++++++- Tests/DefaultsTests/DefaultsTests.swift | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Sources/Defaults/Observation+Combine.swift b/Sources/Defaults/Observation+Combine.swift index 6cac36f..bd27d73 100644 --- a/Sources/Defaults/Observation+Combine.swift +++ b/Sources/Defaults/Observation+Combine.swift @@ -11,15 +11,16 @@ extension Defaults { final class DefaultsSubscription: Subscription where SubscriberType.Input == BaseChange { private var subscriber: SubscriberType? private var observation: UserDefaultsKeyObservation? + private let options: NSKeyValueObservingOptions init(subscriber: SubscriberType, suite: UserDefaults, key: String, options: NSKeyValueObservingOptions) { self.subscriber = subscriber + self.options = options self.observation = UserDefaultsKeyObservation( object: suite, key: key, callback: observationCallback(_:) ) - self.observation?.start(options: options) } func request(_ demand: Subscribers.Demand) { @@ -32,6 +33,10 @@ extension Defaults { subscriber = nil } + func start() { + observation?.start(options: options) + } + private func observationCallback(_ change: BaseChange) { _ = subscriber?.receive(change) } @@ -64,6 +69,7 @@ extension Defaults { ) subscriber.receive(subscription: subscription) + subscription.start() } } diff --git a/Tests/DefaultsTests/DefaultsTests.swift b/Tests/DefaultsTests/DefaultsTests.swift index 059a652..2f2e39a 100644 --- a/Tests/DefaultsTests/DefaultsTests.swift +++ b/Tests/DefaultsTests/DefaultsTests.swift @@ -384,6 +384,27 @@ final class DefaultsTests: XCTestCase { 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 testReceiveValueBeforeSubscriptionCombine() { + let key = Defaults.Key("receiveValueBeforeSubscription", default: "hello") + let expect = expectation(description: "Observation closure being called") + + let publisher = Defaults + .publisher(key, options: [.initial, .new]) + .compactMap { $0.newValue } + .eraseToAnyPublisher() + .collect(2) + + let cancellable = publisher.sink { values in + XCTAssertEqual(["hello", "world"], values) + expect.fulfill() + } + + Defaults[key] = "world"; + cancellable.cancel() + waitForExpectations(timeout: 10) + } + func testObserveKey() { let key = Defaults.Key("observeKey", default: false) let expect = expectation(description: "Observation closure being called")