Waiting for multiple asynchronous download tasks
In Swift 4,
func executeMultiTask() {
//1. Create group
let taskGroup = DispatchGroup()
//2. Enter group
taskGroup.enter()
myTask1.execute(completeHandler: {
// ...
//3. Leave group
taskGroup.leave() //< balance with taskGroup.enter()
})
/* Add more tasks ...
//2. Enter group
taskGroup.enter()
myTask2.execute(completeHandler: {
//3. Leave group
defer {
// Use `defer` to make sure, `leave()` calls are balanced with `enter()`.
taskGroup.leave()
}
// ... more
})
*/
//4. Notify when all task completed at main thread queue.
taskGroup.notify(queue: .main) {
// All tasks are done.
// ...
}
}
To expand on Abhinav's answer, you should:
- Use
dispatch_group_create()
to create a group. - Call
dispatch_group_enter(group)
before starting each download task. - Call
dispatch_group_leave(group)
inside the task's completion handler. - Then call
dispatch_group_notify(group, queue, ^{ ... })
to enqueue a block that will be executed when all the tasks are completed.
You can see an example in this post.
(By the way, it's not true that doing 100 dispatch_async
s in a row will create 100 threads immediately. The system still retains control over how many threads to use to satisfy the queue. However, your code does not wait for any of the tasks to complete before it returns, nor does it attempt to synchronize between multiple tasks completing.)
A working objective-c example for downloading multi files
- (void) downloadFiles: (NSMutableArray *) fileArray : (NSString *)destParentDir{
dispatch_group_t serviceGroup = dispatch_group_create();
for (id fileInfo in fileArray) {
dispatch_group_enter(serviceGroup);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fileName = [fileInfo valueForKey:@"name"];
//Create SubDirs if needed, note that you need to exclude file name for the dirsString :)
//[fileManager createDirectoryAtPath:dirsString withIntermediateDirectories:true attributes:nil error:NULL];
//Download file
NSURL *url = [NSURL URLWithString:@"YOUR_FILE_URL"];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if(urlData)
{
NSString *localPath = [NSString stringWithFormat:@"%@/%@", destParentDir, fileName];
[urlData writeToFile:localPath atomically:YES];
}
dispatch_group_leave(serviceGroup);
}
dispatch_group_notify(serviceGroup, dispatch_get_main_queue(),^{
NSLog(@"Complete files download");
});
}