Загрузка большого количества файлов в фоновом режиме в iOS

У меня есть приложение, в котором я должен загрузить большое количество файлов, от 400 до 900 файлов, всего около 1 ГБ.

Каков наилучший подход для достижения этой цели?

  1. Один NSURLSession и все задачи поставлены в очередь?
  2. Один NSURLSession и ставить задачи по пакетам (например, 10 на 10)?
  3. Несколько NSURLSession с разными очередями?

На самом деле у меня есть NSURLSession во всех задачах (по одной на файл), но иногда я получаю Lost connection to background transfer service.

Вот мой код:

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;
    });
}

}

person Rotten    schedule 21.11.2014    source источник
comment
One NSURLSession and enqueue tasks by packages (10 by 10 for example)? звучит хорошо.   -  person Anoop Vaidya    schedule 21.11.2014
comment
@AnoopVaidya, почему ты так говоришь? Он должен просто создать один фоновый сеанс и добавить к нему свои задачи загрузки. Я не вижу смысла в подходе 10x10.   -  person Rob    schedule 21.11.2014
comment
ты смог скачать все файлы в фоновом режиме?   -  person MD.    schedule 03.06.2016


Ответы (1)


Одна NSURLSession - потому что вы хотите обрабатывать вещи, основанные на сеансе, только один раз (например, авторизация).

Один NSOperationQueue — с несколькими операциями, выполняемыми одновременно. (См. свойство OperationCount). Это может быть немного сложно реализовать NSOperation в первый раз, но я уверен, что это будет ваш лучший выбор. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/index.html

http://nshipster.com/nsoperation/

Да, кстати, это очень объектно-ориентированный подход, что всегда приятно =)

person fabianfett    schedule 21.11.2014
comment
Нет нет нет! Я большой поклонник упаковки сетевых запросов в NSOperation, но это единственный сценарий, когда вы определенно не делаете этого. Конфигурация фонового сеанса — это конфигурация, в которой запросы продолжают выполняться долгое время после закрытия приложения и после уничтожения NSOperationQueue и связанных с ним объектов NSOperation. Кроме того, в отличие от стандартных объектов конфигурации сеанса, где наличие maxConcurrentOperationCount имеет реальную ценность, здесь оно просто мешает. С фоновыми сеансами вы хотите немедленно создавать экземпляры всех запросов на загрузку! - person Rob; 22.11.2014
comment
Хорошо, это имеет большой смысл. Таким образом, даже если приложение приостановлено, сетевой запрос должен продолжать загружаться. Верно? К сожалению, из-за этого нужно было бы иметь два разных способа реализации загрузки. Способ работы будет работать только с фоновым сеансом, верно? - person fabianfett; 22.11.2014
comment
Фоновые задачи продолжают выполняться не только тогда, когда приложение приостановлено, но даже после того, как приложение полностью завершено (например, если ОС отбрасывает его из-за нехватки памяти). Единственное, о чем знает фоновый демон, — это задачи, и любая очередь операций (и все, что находится в очереди) давно исчезнет. Таким образом, очередь операций великолепна для сеансов переднего плана, но будет мешать только фоновым сеансам. Таким образом, способ работы будет работать только с сеансами не в фоновом режиме (т. е. по умолчанию или эфемерными). (Я полагаю, это то, что вы хотели сказать, лол.) - person Rob; 22.11.2014