I have a app which downloads a huge amount of data (mostly images and document files) when it is installed for the first time. Currently, I'm only able to display the progress in a HUD. But I wish I could somehow allow the data to be downloaded when the app goes into background (or device gets locked). As the app is being targeted for devices running iOS 7.0 and above, I'm using NSURLSession
to download the data. I've gone through various threads here on Stackoverflow as well as a tutorial here. Even after making changes to my app as per the tutorial, my app does not continue the download. I tested it on an iPad. When the app is sent to background(or locked), the download is paused and resumes when the app comes to foreground.
I'm unsure if my approach is wrong or my implementation is flawed. Any help/advice is welcome.
The flow of the app is as follows: 'LoginViewController' calls an internal method
downloadData
which has an object of theSaveProjectData
class that performs the task of downloading.
LoginViewController.m
@implementation LoginViewController
- (void)viewDidLoad {
}
- (IBAction)sumitButtonDidClick:(id)sender {
if ([self checkNetworkConnection] ==NotReachable) {
UIAlertView * alertView=[[UIAlertView alloc] initWithTitle:@"Network Error" message:@"No internet Connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alertView show];
} else {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeDeterminateHorizontalBar;
hud.label.text = NSLocalizedString(@"Downloading...", @"HUD loading title");
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
if ([self loginStatus]) {
NSString * userName = self.user_nameTxtField.text;
CallProjectAPI * callProjectAPIinst = [[CallProjectAPI alloc] init];
NSString * appStatus = [[NSUserDefaults standardUserDefaults] objectForKey:@"appStatus"];
if ([appStatus isEqualToString:@"N"]) {
[callProjectAPIinst dataFromJSONFile];
[callProjectAPIinst saveImageName];
} else {
[self doSomeWorkWithProgress];
[callProjectAPIinst callAPI];
[self doSomeWorkWithProgress];
[self downloadData];
}
hud.label.text = NSLocalizedString(@"Complete!", @"HUD completed title");
porjectVC = [self.storyboard instantiateViewControllerWithIdentifier:@"ProjectViewController"];
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self presentViewController:porjectVC animated:YES completion:nil];
[hud hideAnimated:YES];
});
[[NSUserDefaults standardUserDefaults] setObject:userName forKey:@"userName"];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[hud hideAnimated:YES];
UIAlertView * alert=[[UIAlertView alloc] initWithTitle:@"Alert" message:@"User Name or Password is wrong." delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil];
[alert show];
});
}
});
}
}
-(void)downloadData{
if ([self checkNetworkConnection] ==NotReachable) {
UIAlertView * alertView=[[UIAlertView alloc] initWithTitle:@"Network Error" message:@"No internet Connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alertView show];
} else {
NSString * status =[[NSUserDefaults standardUserDefaults] objectForKey:@"DownloadData"];
if (status == nil) {
SaveProjectData * saveProjectDataInst = [[SaveProjectData alloc] init];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveAboutImage];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveConstructionUpdateImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveLogImages];
[saveProjectDataInst saveSmallImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveFloorPlanImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveUnitPlanImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveMasterPlanImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveBrochurs];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveGalleryImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveAmenitiesImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveVideos];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveMapImage];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveBannerImage];
[self doSomeWorkWithProgress];
[saveProjectDataInst savewalkthrough];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveFlatImages];
[self doSomeWorkWithProgress];
[saveProjectDataInst saveEventImages];
[self doSomeWorkWithProgress];
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DownloadData"];
[saveProjectDataInst getUpdatedListForEachProject];
}
}
}
- (void)doSomeWorkWithProgress {
progress += 0.049f;
dispatch_async(dispatch_get_main_queue(), ^{
// Instead we could have also passed a reference to the HUD
// to the HUD to myProgressTask as a method parameter.
[MBProgressHUD HUDForView:self.view].progress = progress;
});
}
@end
Another approach could be to provide a button that the user clicks and data is downloaded while the user can still continue to use the device for other perposes. Any pointers as to how I can implement it?