|
@@ -16,7 +16,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|
var locationManager: LocationManager!
|
|
var locationManager: LocationManager!
|
|
var notificationManager: NotificationManager!
|
|
var notificationManager: NotificationManager!
|
|
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
|
|
private var backgroundTask: UIBackgroundTaskIdentifier = .invalid
|
|
- private var fetchBackgroundTasks = [Double: UIBackgroundTaskIdentifier]()
|
|
|
|
var reachability = Reachability()!
|
|
var reachability = Reachability()!
|
|
var window: UIWindow?
|
|
var window: UIWindow?
|
|
var notifyToken: String?
|
|
var notifyToken: String?
|
|
@@ -346,24 +345,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|
increaseDebugCounter("notify-local-wakeup")
|
|
increaseDebugCounter("notify-local-wakeup")
|
|
performFetch(completionHandler: completionHandler)
|
|
performFetch(completionHandler: completionHandler)
|
|
}
|
|
}
|
|
-
|
|
|
|
- private func unregisterFetchBackgroundTask(timestamp: Double) {
|
|
|
|
- let backgroundTask = fetchBackgroundTasks[timestamp]
|
|
|
|
- if let backgroundTask = backgroundTask, backgroundTask != .invalid {
|
|
|
|
- UIApplication.shared.endBackgroundTask(backgroundTask)
|
|
|
|
- fetchBackgroundTasks.removeValue(forKey: timestamp)
|
|
|
|
- logger.info("⬅️ fetch background task ended and removed: \(timestamp)")
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private func registerFetchBackgroundTask(timestamp: Double) {
|
|
|
|
- logger.info("⬅️ registering fetch background task: \(timestamp)")
|
|
|
|
- let backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
|
|
|
|
- logger.info("⬅️ fetch background expirationHandler called")
|
|
|
|
- self?.unregisterFetchBackgroundTask(timestamp: timestamp)
|
|
|
|
- }
|
|
|
|
- fetchBackgroundTasks[timestamp] = backgroundTask
|
|
|
|
- }
|
|
|
|
|
|
|
|
private func performFetch(completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
private func performFetch(completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
// `didReceiveRemoteNotification` as well as `performFetchWithCompletionHandler` might be called if we're in foreground,
|
|
// `didReceiveRemoteNotification` as well as `performFetchWithCompletionHandler` might be called if we're in foreground,
|
|
@@ -389,7 +370,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|
return
|
|
return
|
|
}
|
|
}
|
|
bgIoTimestamp = nowTimestamp
|
|
bgIoTimestamp = nowTimestamp
|
|
- registerFetchBackgroundTask(timestamp: nowTimestamp)
|
|
|
|
|
|
+
|
|
|
|
+ // make sure to balance each call to `beginBackgroundTask` with `endBackgroundTask`
|
|
|
|
+ let backgroundTask = UIApplication.shared.beginBackgroundTask {
|
|
|
|
+ // TODO: currently, this should be okay, we are not using too much background time,
|
|
|
|
+ // so that handler should never be called.
|
|
|
|
+ // the plan is to listen to an event as DC_EVENT_ENTER_IDLE and stop fetch from there.
|
|
|
|
+ // if we have such an event, we could imprive this handler and fire the event.
|
|
|
|
+ logger.info("fetch background task will end soon")
|
|
|
|
+ }
|
|
|
|
|
|
// we're in background, run IO for a little time
|
|
// we're in background, run IO for a little time
|
|
dcContext.maybeStartIo()
|
|
dcContext.maybeStartIo()
|
|
@@ -408,10 +397,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
|
|
|
|
|
// to avoid 0xdead10cc exceptions, scheduled jobs need to be done before we get suspended;
|
|
// to avoid 0xdead10cc exceptions, scheduled jobs need to be done before we get suspended;
|
|
// we increase the probabilty that this happens by waiting a moment before calling completionHandler()
|
|
// we increase the probabilty that this happens by waiting a moment before calling completionHandler()
|
|
- DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
|
|
|
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
logger.info("⬅️ fetch done")
|
|
logger.info("⬅️ fetch done")
|
|
- self?.unregisterFetchBackgroundTask(timestamp: nowTimestamp)
|
|
|
|
completionHandler(.newData)
|
|
completionHandler(.newData)
|
|
|
|
+
|
|
|
|
+ // this line should always be reached after a background task is started
|
|
|
|
+ // and balances the call to `beginBackgroundTask` above.
|
|
|
|
+ UIApplication.shared.endBackgroundTask(backgroundTask)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|