Fix crash in the Combine API (#39)

This commit is contained in:
Kacper Rączy 2020-04-05 16:56:59 +02:00 committed by GitHub
parent ca813bf449
commit 3275717838
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 1 deletions

View File

@ -11,15 +11,16 @@ extension Defaults {
final class DefaultsSubscription<SubscriberType: Subscriber>: Subscription where SubscriberType.Input == BaseChange { final class DefaultsSubscription<SubscriberType: Subscriber>: Subscription where SubscriberType.Input == BaseChange {
private var subscriber: SubscriberType? private var subscriber: SubscriberType?
private var observation: UserDefaultsKeyObservation? private var observation: UserDefaultsKeyObservation?
private let options: NSKeyValueObservingOptions
init(subscriber: SubscriberType, suite: UserDefaults, key: String, options: NSKeyValueObservingOptions) { init(subscriber: SubscriberType, suite: UserDefaults, key: String, options: NSKeyValueObservingOptions) {
self.subscriber = subscriber self.subscriber = subscriber
self.options = options
self.observation = UserDefaultsKeyObservation( self.observation = UserDefaultsKeyObservation(
object: suite, object: suite,
key: key, key: key,
callback: observationCallback(_:) callback: observationCallback(_:)
) )
self.observation?.start(options: options)
} }
func request(_ demand: Subscribers.Demand) { func request(_ demand: Subscribers.Demand) {
@ -32,6 +33,10 @@ extension Defaults {
subscriber = nil subscriber = nil
} }
func start() {
observation?.start(options: options)
}
private func observationCallback(_ change: BaseChange) { private func observationCallback(_ change: BaseChange) {
_ = subscriber?.receive(change) _ = subscriber?.receive(change)
} }
@ -64,6 +69,7 @@ extension Defaults {
) )
subscriber.receive(subscription: subscription) subscriber.receive(subscription: subscription)
subscription.start()
} }
} }

View File

@ -384,6 +384,27 @@ final class DefaultsTests: XCTestCase {
waitForExpectations(timeout: 10) 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<String>("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() { func testObserveKey() {
let key = Defaults.Key<Bool>("observeKey", default: false) let key = Defaults.Key<Bool>("observeKey", default: false)
let expect = expectation(description: "Observation closure being called") let expect = expectation(description: "Observation closure being called")