From 3efa6406db7d0fd167d0fc39a5e5e85c7ee46d57 Mon Sep 17 00:00:00 2001 From: dougzilla32 Date: Sun, 7 Oct 2018 15:12:46 +0900 Subject: [PATCH 1/2] 'Cancel' for PromiseKit -- provides the ability to cancel promises and promise chains --- Cartfile | 3 ++- Cartfile.resolved | 2 +- Sources/HealthKit+Promise.swift | 44 ++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Cartfile b/Cartfile index 2bfea98..c517d21 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1,2 @@ -github "mxcl/PromiseKit" ~> 6.0 +#github "mxcl/PromiseKit" ~> 6.0 +github "dougzilla32/PromiseKit" "CoreCancel" diff --git a/Cartfile.resolved b/Cartfile.resolved index a1699c6..80a4000 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "mxcl/PromiseKit" "6.4.1" +github "dougzilla32/PromiseKit" "087b3cf470890ff9ea841212e2f3e285fecf3988" diff --git a/Sources/HealthKit+Promise.swift b/Sources/HealthKit+Promise.swift index 03029c4..8fd51a3 100644 --- a/Sources/HealthKit+Promise.swift +++ b/Sources/HealthKit+Promise.swift @@ -32,8 +32,12 @@ public extension HKStatisticsQuery { public extension HKAnchoredObjectQuery { static func promise(type: HKSampleType, predicate: NSPredicate? = nil, anchor: HKQueryAnchor? = nil, limit: Int = HKObjectQueryNoLimit, healthStore: HKHealthStore = .init()) -> Promise<([HKSample], [HKDeletedObject], HKQueryAnchor)> { - return Promise { seal in - let query = HKAnchoredObjectQuery(type: type, predicate: predicate, anchor: anchor, limit: limit) { + var query: HKAnchoredObjectQuery! + var reject: ((Error) -> Void)! + + let promise = Promise<([HKSample], [HKDeletedObject], HKQueryAnchor)> { seal in + reject = seal.reject + query = HKAnchoredObjectQuery(type: type, predicate: predicate, anchor: anchor, limit: limit) { if let a = $1, let b = $2, let c = $3 { seal.fulfill((a, b, c)) } else if let e = $4 { @@ -44,13 +48,16 @@ public extension HKAnchoredObjectQuery { } healthStore.execute(query) } + + promise.setCancellableTask(LongRunningQuery(healthStore: healthStore, query: query), reject: reject) + return promise } } public extension HKStatisticsCollectionQuery { func promise(healthStore: HKHealthStore = .init()) -> Promise { - return Promise { seal in + return Promise(cancellableTask: LongRunningQuery(healthStore: healthStore, query: self)) { seal in initialResultsHandler = { seal.resolve($1, $2) } @@ -69,3 +76,34 @@ public extension HKSampleQuery { } } } + +class LongRunningQuery: CancellableTask { + let healthStore: HKHealthStore + let query: HKQuery + + init(healthStore: HKHealthStore, query: HKQuery) { + self.healthStore = healthStore + self.query = query + } + + func cancel() { + healthStore.stop(query) + isCancelled = true + } + + var isCancelled = false +} + +//////////////////////////////////////////////////////////// Cancellable wrappers + +public extension HKAnchoredObjectQuery { + static func cancellablePromise(type: HKSampleType, predicate: NSPredicate? = nil, anchor: HKQueryAnchor? = nil, limit: Int = HKObjectQueryNoLimit, healthStore: HKHealthStore = .init()) -> CancellablePromise<([HKSample], [HKDeletedObject], HKQueryAnchor)> { + return cancellable(promise(type: type, predicate: predicate, anchor: anchor, limit: limit, healthStore: healthStore)) + } +} + +public extension HKStatisticsCollectionQuery { + func cancellablePromise(healthStore: HKHealthStore = .init()) -> CancellablePromise { + return cancellable(promise(healthStore: healthStore)) + } +} From 8168dfcfec3ec0f75cf25773e21749870a00c3ea Mon Sep 17 00:00:00 2001 From: dougzilla32 Date: Tue, 16 Oct 2018 11:53:02 +0900 Subject: [PATCH 2/2] 'Cancel' for PromiseKit -- remove cancellable wrappers (they are unnecessary) --- Sources/HealthKit+Promise.swift | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Sources/HealthKit+Promise.swift b/Sources/HealthKit+Promise.swift index 8fd51a3..9cad459 100644 --- a/Sources/HealthKit+Promise.swift +++ b/Sources/HealthKit+Promise.swift @@ -31,6 +31,8 @@ public extension HKStatisticsQuery { } public extension HKAnchoredObjectQuery { + /// - Note: cancelling this promise will cancel the underlying task + /// - SeeAlso: [Cancellation](http://promisekit.org/docs/) static func promise(type: HKSampleType, predicate: NSPredicate? = nil, anchor: HKQueryAnchor? = nil, limit: Int = HKObjectQueryNoLimit, healthStore: HKHealthStore = .init()) -> Promise<([HKSample], [HKDeletedObject], HKQueryAnchor)> { var query: HKAnchoredObjectQuery! var reject: ((Error) -> Void)! @@ -56,6 +58,8 @@ public extension HKAnchoredObjectQuery { } public extension HKStatisticsCollectionQuery { + /// - Note: cancelling this promise will cancel the underlying task + /// - SeeAlso: [Cancellation](http://promisekit.org/docs/) func promise(healthStore: HKHealthStore = .init()) -> Promise { return Promise(cancellableTask: LongRunningQuery(healthStore: healthStore, query: self)) { seal in initialResultsHandler = { @@ -93,17 +97,3 @@ class LongRunningQuery: CancellableTask { var isCancelled = false } - -//////////////////////////////////////////////////////////// Cancellable wrappers - -public extension HKAnchoredObjectQuery { - static func cancellablePromise(type: HKSampleType, predicate: NSPredicate? = nil, anchor: HKQueryAnchor? = nil, limit: Int = HKObjectQueryNoLimit, healthStore: HKHealthStore = .init()) -> CancellablePromise<([HKSample], [HKDeletedObject], HKQueryAnchor)> { - return cancellable(promise(type: type, predicate: predicate, anchor: anchor, limit: limit, healthStore: healthStore)) - } -} - -public extension HKStatisticsCollectionQuery { - func cancellablePromise(healthStore: HKHealthStore = .init()) -> CancellablePromise { - return cancellable(promise(healthStore: healthStore)) - } -}