From 645ffa673411270deafb339c07a4f0c0d71a198d Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Tue, 24 Nov 2020 16:33:58 -0300 Subject: [PATCH] FIX: download operation gets cancelled when apps are backgrounded --- .../UIKit/Synchronizer/SDKSynchronizer.swift | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index 83c96474..3d1b86f9 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -88,6 +88,8 @@ public class SDKSynchronizer: Synchronizer { public private(set) var blockProcessor: CompactBlockProcessor? public private(set) var initializer: Initializer + private var isSubscribedToAppDelegateEvents = false + private var transactionManager: OutboundTransactionManager private var transactionRepository: TransactionRepository var taskIdentifier: UIBackgroundTaskIdentifier = .invalid @@ -112,7 +114,6 @@ public class SDKSynchronizer: Synchronizer { transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer), transactionRepository: initializer.transactionRepository) - self.subscribeToAppDelegateNotifications() } init(status: Status, @@ -131,19 +132,32 @@ public class SDKSynchronizer: Synchronizer { self.blockProcessor = nil self.taskIdentifier = .invalid } + + private func lazyInitialize() throws { + guard self.blockProcessor == nil else { return } + guard let processor = initializer.blockProcessor() else { + throw SynchronizerError.generalError(message: "compact block processor initialization failed") + } + + if !isSubscribedToAppDelegateEvents { + subscribeToAppDelegateNotifications() + } + subscribeToProcessorNotifications(processor) + + self.blockProcessor = processor + } /** Starts the synchronizer - Throws: CompactBlockProcessorError when failures occur */ public func start(retry: Bool = false) throws { - guard let processor = initializer.blockProcessor() else { + try lazyInitialize() + + guard let processor = self.blockProcessor else { throw SynchronizerError.generalError(message: "compact block processor initialization failed") } - subscribeToProcessorNotifications(processor) - - self.blockProcessor = processor guard status == .stopped || status == .disconnected || status == .synced else { assert(true,"warning: synchronizer started when already started") // TODO: remove this assertion sometime in the near future return @@ -154,7 +168,6 @@ public class SDKSynchronizer: Synchronizer { } catch { throw mapError(error) } - } /** @@ -174,9 +187,38 @@ public class SDKSynchronizer: Synchronizer { } // MARK: event subscription + + private func subscribeFromAppDelegateNotifications() { + self.isSubscribedToAppDelegateEvents = true + + let center = NotificationCenter.default + + center.removeObserver(self, + name: UIApplication.didBecomeActiveNotification, + object: nil) + + center.removeObserver(self, + name: UIApplication.willTerminateNotification, + object: nil) + + center.removeObserver(self, + name: UIApplication.willResignActiveNotification, + object: nil) + + center.removeObserver(self, + name: UIApplication.didEnterBackgroundNotification, + object: nil) + + center.removeObserver(self, + name: UIApplication.willEnterForegroundNotification, + object: nil) + + } + private func subscribeToAppDelegateNotifications() { // todo: iOS 13 platform specific + self.isSubscribedToAppDelegateEvents = true let center = NotificationCenter.default center.addObserver(self, @@ -399,9 +441,10 @@ public class SDKSynchronizer: Synchronizer { invalidateBackgroundActivity() if status == .stopped || status == .disconnected { do { - try start() + try start(retry: true) } catch { self.status = .disconnected + self.notifyFailure(error) } } }