У меня есть async NSOperation
для загрузки данных для нескольких объектов ImageFile
. Поскольку все это происходит асинхронно, я использую группу отправки для отслеживания запросов, а затем dispatch_group_notify
для завершения операции, когда все это делается.Что происходит с unmatched dispatch_group_enter и dispatch_group_leave?
Вопрос, который у меня есть, заключается в том, что происходит, когда операция заканчивается преждевременно, либо путем отмены, либо какой-либо другой ошибкой. Группа отправки будет оставлена с непревзойденными dispatch_group_enter
и dispatch_group_leave
, так что dispatch_group_notify
никогда не будет вызываться. Является ли этот блок сохраненным где-то в системе навсегда ожидающим, или он будет освобожден, когда выйдет NSOperation
?
Или мой подход не идеален, как еще я должен это делать?
- (void)main
{
if (self.cancelled) {
[self completeOperation];
return;
}
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
context.persistentStoreCoordinator = self.persistentStoreCoordinator;
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
[context performBlock:^{
NSFetchRequest *request = [ImageFile fetchRequest];
request.predicate = ....
request.sortDescriptors = ...
NSError *error;
NSArray *imageFiles = [context executeFetchRequest:request error:&error];
if (!imageFiles) {
// Error handling...
[self completeOperation];
return;
}
dispatch_group_t group = dispatch_group_create();
for (ImageFile *imageFile in imageFiles) {
dispatch_group_enter(group);
@autoreleasepool {
[self.webService requestImageWithId:imageFile.id completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (self.cancelled) {
[self completeOperation];
return;
}
[context performBlock:^{
if (data && !error) {
imageFile.data = data;
NSError *error;
if (![context save:&error]) {
// Error handling...
[self completeOperation];
return;
}
}
dispatch_group_leave(group);
}];
}];
}
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self completeOperation];
});
}];
}