Ответ 1
Как упоминалось в комментариях Filip и Rob, медленность заключается в том, что когда NSURLSession
инициализируется backgroundSessionConfigurationWithIdentifier:
, задачи загрузки будут выполняться в фоновом режиме, независимо от того, находится ли приложение на переднем плане. Поэтому я решил эту проблему, имея 2 экземпляра NSURLSession
: один для загрузки переднего плана и один для загрузки фона:
NSURLSessionConfiguration *foregroundSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
foregroundSessionConfig.HTTPMaximumConnectionsPerHost = 40;
foregroundSession = [NSURLSession sessionWithConfiguration:foregroundSessionConfig
delegate:self
delegateQueue:nil];
[foregroundSession retain];
NSURLSessionConfiguration *backgroundSessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.terato.darknessfallen.BackgroundDownload"];
backgroundSessionConfig.HTTPMaximumConnectionsPerHost = 40;
backgroundSession = [NSURLSession sessionWithConfiguration:backgroundSessionConfig
delegate:self
delegateQueue:nil];
[backgroundSession retain];
Когда приложение переключается на фоновый режим, я просто вызываю cancelByProducingResumeData:
для каждой из загружаемых задач, которые все еще выполняются, а затем передают его на downloadTaskWithResumeData:
:
- (void)switchToBackground
{
if (state == kDownloadManagerStateForeground) {
[foregroundSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithResumeData:resumeData];
[downloadTask resume];
}];
}
}];
state = kDownloadManagerStateBackground;
}
}
Аналогично, когда приложение переключается на передний план, я делаю то же самое, но переключился foregroundSession
на backgroundSession
:
- (void)switchToForeground
{
if (state == kDownloadManagerStateBackground) {
[backgroundSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSURLSessionDownloadTask *downloadTask = [foregroundSession downloadTaskWithResumeData:resumeData];
[downloadTask resume];
}];
}
}];
state = kDownloadManagerStateForeground;
}
}
Кроме того, не забудьте вызвать beginBackgroundTaskWithExpirationHandler:
перед вызовом switchToBackground
, когда приложение переключится на фоновый. Это делается для того, чтобы метод мог быть завершен в фоновом режиме. В противном случае он будет вызываться только после того, как приложение снова войдет в план.