Download large number of files in background in iOS
Asked Answered
B

1

6

I have an app in which I have to download a large number of files, from 400 to 900 files that are about 1GB total.

Which is the best approach to accomplish this?

  1. One NSURLSession and all task enqueued in it?
  2. One NSURLSession and enqueue tasks by packages (10 by 10 for example)?
  3. Multiple NSURLSession with different queues?

Actually I have a NSURLSession within all task (one per file) enqueued, but sometimes I get a Lost connection to background transfer service.

Here is my code:

if([[UIDevice currentDevice] isMultitaskingSupported])
{
    __block UIBackgroundTaskIdentifier bgTask;

    UIApplication *application = [UIApplication sharedApplication];

    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSString *uuidString;
        CFUUIDRef uuid = CFUUIDCreate(nil);
        uuidString = CFBridgingRelease(CFUUIDCreateString(nil, uuid));
        CFRelease(uuid);
        //            }

        NSURLSessionConfiguration *sessionConfiguration;

        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0"))
        {
            sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.fiveflamesmobile.bakgroundDownload"];
        }
        else
        {
            sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.fiveflamesmobile.bakgroundDownload"];
        }
        sessionConfiguration.HTTPMaximumConnectionsPerHost = 5;
        sessionConfiguration.sessionSendsLaunchEvents = YES;
        sessionConfiguration.discretionary = YES;
        sessionConfiguration.timeoutIntervalForResource = 0; //NO timeout
        sessionConfiguration.timeoutIntervalForRequest = 0; //No timeout
        sessionConfiguration.networkServiceType = NSURLNetworkServiceTypeBackground;

        self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                     delegate:self
                                                delegateQueue:nil];

        NSLog(@"##### ------- Sesion created succesfully");

        //    [self batchDownloading];

        for (id<FFDownloadFileProtocol> file in self.selectedCatalogProducto.downloadInfo.arrayFiles)
        {
            [self startDownloadFile:file];
        }

        NSLog(@"##### ------- Download tasks created successfully ------");

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
}

}
Balliett answered 21/11, 2014 at 13:14 Comment(3)
One NSURLSession and enqueue tasks by packages (10 by 10 for example)? sounds good.Theory
@AnoopVaidya why do you say that? He should just create single background session and add his download tasks to that. I see no value in the 10x10 approach.Appoggiatura
were you able to download all files in background?Thingumabob
O
1

One NSURLSession - because you only want to handle session based things just once (auth for example).

One NSOperationQueue - with multiple operations running at the same time. (See property operationCount). It might be a little tricky implementing a NSOperation for the first time, but I'm sure this would be your best bet. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/index.html

http://nshipster.com/nsoperation/

Oh and by the way, this is a highly object oriented approach, which is always nice =)

Orling answered 21/11, 2014 at 15:21 Comment(3)
No, no, no! I'm a huge fan of wrapping network requests in NSOperation, but this is the one and only scenario where you definitely do not to do that. A background session configuration is one where the requests continue to run long after the app is terminated and after the NSOperationQueue and its associated NSOperation objects have been destroyed. Plus, unlike standard session configuration objects, where having maxConcurrentOperationCount offers real value, here it just gets in the way. With background sessions, you want to instantiate all of the download requests immediately!Appoggiatura
Okay, that's makes a lot of sense. That way even if the app is suspended the network request should continue to load. Right? Sadly though, because of that one would have need to have two different ways of implementing the download. The operation way would only work with a background session, right?Orling
The background tasks continue to run not only when the app is suspended, but even after the app is completely terminated (e.g. if OS jettisons it due to memory pressure). The only thing that the background daemon knows about are the tasks, and any operation queue (and anything pending on the queue) will be long gone. So operation queue is fabulous for foreground sessions, but will only interfere with background sessions. So the "operation way would only work with" non-background (i.e. default or ephemeral) sessions. (I assume that's what you meant to say. Lol.)Appoggiatura

© 2022 - 2024 — McMap. All rights reserved.