I have a content that consists of main file and additional files.
So here is the problem: At first I need to download,unpack and insert into database additional files and only then do the same thing for main file. Additional files are needed to be downloaded serial, and main file must be downloaded after them.
What is the right way to do it?
Right now I'm doing it this way:
- (void)checkIfPlacesAreDownloaded:(NSArray *)places{
[SVProgressHUD showWithStatus:@"Downloading places"];
dispatch_group_t group = dispatch_group_create();
for(NSDictionary *place in places){
BOOL result = [IDGDatabaseManager checkIfPlaceIsDownloaded:place];
if(!result){
dispatch_group_enter(group);
[self downloadPlace:place withCompletionHandler:^{
[IDGDatabaseManager setPlaceDownloaded:[place objectForKey:@"place_ID"]
WithCompletionBlock:^(BOOL success, NSError *error) {
dispatch_group_leave(group);
}];
}];
}
}
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self downloadExcursionWithParams:self.excursionDownloadResponse];
});
}
It only works if there is one file in "places" array. If there is more than one file they start to be downloaded parallel and it is not suitable for me.
I think that downloadPlace:withCompletionHandler:
method works asynchronously on the background concurrent queue. That is why the file downloads run in parallel. I'd use a private serial queue instead or simply do the next:
[SVProgressHUD showWithStatus:@"Downloading places"];
dispatch_group_t group = dispatch_group_create();
// create a serial background queue to run the file downloads
dispatch_queue_attr_t qosAttribute = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
dispatch_queue_t myQueue = dispatch_queue_create("com.YourApp.YourQueue", qosAttribute);
for(NSDictionary *place in places){
BOOL result = [IDGDatabaseManager checkIfPlaceIsDownloaded:place];
if(!result){
dispatch_group_enter(group);
// run the download async on the serial bg queue
__weak __typeof(self) weakSelf = self;
dispatch_async(myQueue, ^{
__typeof(self) strongSelf = self;
// we need a semaphore to wait for the download completion
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[strongSelf downloadPlace:place withCompletionHandler:^{
[IDGDatabaseManager setPlaceDownloaded:[place objectForKey:@"place_ID"]
WithCompletionBlock:^(BOOL success, NSError *error) {
dispatch_semaphore_signal(sema);
}];
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_group_leave(group);
});
}
}
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self downloadExcursionWithParams:self.excursionDownloadResponse];
});