Итак, я создаю свою загрузку в основном потоке
NSURLRequest *request = [NSURLRequest requestWithURL:download.URL];
NSURLSessionDownloadTask *downloadTask = [self.downloadSession downloadTaskWithRequest:request];
[downloadTask resume];
и добавив NSManagedContextID, связанный с загрузкой, в NSMutableDictionary, поэтому я могу получить его позже в call-backs делегата
[self.downloads setObject:[download objectID] forKey:[NSNumber numberWithInteger:downloadTask.taskIdentifier]];
Мой self.downloadSession
выше настроен следующим образом
- (NSURLSession *)backgroundSession
{
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.test.backgroundSession"];
configuration.discretionary = YES;
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
});
return session;
}
Моя проблема заключается в том, что обратные вызовы делегатов, кажется, вызываются в разных потоках
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSManagedObjectID *downloadID = [self.downloads objectForKey:[NSNumber numberWithInteger:downloadTask.taskIdentifier]];
double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:downloadID,@"download",[NSNumber numberWithDouble:progress],@"progress", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DownloadProgress" object:nil userInfo:userInfo];
}
Поэтому, когда я получаю доступ к self.downloads, чтобы получить правильный идентификатор объекта, я фактически получаю доступ к NSMutableDictionary из другого потока, чем тот, на котором он был создан, и я считаю, что NSMutableDictionary не является потокобезопасным. Итак, какое лучшее решение для этого, я мог бы использовать что-то вроде этого
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
при объявлении сеанса установите очередь делегатов в mainQueue, которая вызывает всех делегатов для вызова в основном потоке, но я хотел бы сохранить все обратные вызовы в фоновом потоке, если это возможно.