Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix]Ensuring background task expiration #261

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//

import Foundation
import Combine

/// Object responsible for platform specific handling of background tasks
protocol BackgroundTaskScheduler {
Expand Down Expand Up @@ -31,7 +32,15 @@ class IOSBackgroundTaskScheduler: BackgroundTaskScheduler {
}()

/// The identifier of the currently running background task. `nil` if no background task is running.
private var activeBackgroundTask: UIBackgroundTaskIdentifier?
private var activeBackgroundTask: UIBackgroundTaskIdentifier? {
didSet {
if let oldBackgroundTask = oldValue {
app?.endBackgroundTask(oldBackgroundTask)
}
}
}

private var backgroundTaskExpirationCancellable: AnyCancellable?

var isAppActive: Bool {
let app = self.app
Expand All @@ -51,11 +60,33 @@ class IOSBackgroundTaskScheduler: BackgroundTaskScheduler {
}

func beginTask(expirationHandler: (() -> Void)?) -> Bool {
activeBackgroundTask = app?.beginBackgroundTask { [weak self] in
let expirationHandler = { [weak self] in
expirationHandler?()
self?.endTask()
self?.backgroundTaskExpirationCancellable?.cancel()
self?.backgroundTaskExpirationCancellable = nil
}

// Cancel any existing task before starting a new one.
backgroundTaskExpirationCancellable?.cancel()

activeBackgroundTask = app?.beginBackgroundTask(
expirationHandler: expirationHandler
)

guard activeBackgroundTask != .invalid else {
return false
}
return activeBackgroundTask != .invalid

// Set a timer for 30 seconds(which is the max the OS will give us anyway)
// to stop our task if we end up not getting the call from OS. In that
// way we avoid getting killed by the OS.
backgroundTaskExpirationCancellable = Foundation.Timer
.publish(every: 30, on: .main, in: .default)
.autoconnect()
.sink { _ in expirationHandler() }

return true
}

func endTask() {
Expand Down
Loading