Reputation: 29
I have an iOS application where the user can trigger a lengthy update process by tapping on a button. The update process involves making API calls that can take a few minutes to complete. Everything works fine when the user stays in the foreground, but if the user switches to the background, the app is not able to fetch all the necessary data.
I would like to implement a solution where, upon tapping the update button, the update process can continue running even if the app enters the background. I want to request additional background execution time to ensure that the update process completes successfully.
Based on my research, I've learned about the beginBackgroundTask(expirationHandler:)
method provided by the UIApplication
class, which allows an app to request additional background execution time. However, I'm unsure how to implement it correctly in my app.
Here's the current flow in my app:
The user taps the "Update" button, triggering the updateData()
function.
Inside updateData()
, I make the necessary API calls to fetch the required data.
If the app is in the foreground, everything works fine. However, if the app enters the background during the update process, the data fetching is incomplete.
I would like to modify the updateData()
function to request additional background execution time so that the update process can continue running until it completes, regardless of whether the app is in the foreground or background.
Could you provide guidance on how to implement this correctly? Any code examples or suggestions would be greatly appreciated.
PS. If I use a BGTask
as I understand the BGTask
only runs when user goes to the background mode. Is there any way to run the updateData()
with a BGTask
wether the app stays in foreground or background? The user might stay in foreground until the update finishes or they may go to the background. That's my main issue.
Thank you!
Upvotes: 0
Views: 1324
Reputation: 10417
First, beginBackgroundTask
and BGTask
are somewhat orthogonal. The beginBackgroundTask
or beginBackgroundTaskWithName
method might be appropriate for your use case. The latter, as I understand it, is mostly for doing updates while your app isn't running, so that's probably not what you're trying to do.
For the beginBackgroundTask
approach, I would create a single background task independent of your network requests right before you issue the first outstanding network request, and then mark the background as done when the last task has completed and the data has been processed.
For example, if you put all your network tasks in a single NSURLSession, your completion handler block could end with a call like this:
[someAppSpecificObject callBackgroundTaskCompletionIfNeededForSession:session];
and that method would do something like this:
@property(nonatomic) NSMutableDictionary *<NSURLSession *, NSNumber *> *backgroundTaskIdentifiers;
- (void)callBackgroundTaskCompletionIfNeededForSession:(NSURLSession *)session {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[session getAllTasksWithCompletionHandler:^(NSArray<NSURLSessionTask *> *tasks) {
if (!tasks.count) {
UIBackgroundTaskIdentifier identifier = [self. backgroundTaskIdentifiers[session] integerValue];
[[UIApplication sharedApplication] endBackgroundTask:identifier];
}
}
}
}
or if you have the potential for multiple requests outstanding that are not all queued up on the session at once, do something similar using the internal data structure of your choice.
However, if it is at all possible, it would be better to use an NSURLSessionDownloadTask
to kick off the long-running job, and rely on the app getting woken up or launched in the background to process the data when the task completes. That approach is friendlier on the battery, with the caveat that issuing additional requests when the long-running request completes may result in rapidly diminishing performance, so if that is needed, it might be better to save the data, and complete the processing work when the app is next in the foreground.
Upvotes: 0