Reputation: 12981
I follow RAY WENDERLICH GCD tutorial- part 2, and I don't get this:
First implementation
- (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1
__block NSError *error;
dispatch_group_t downloadGroup = dispatch_group_create(); // 2
for (NSInteger i = 0; i < 3; i++) {
NSURL *url;
switch (i) {
case 0:
url = [NSURL URLWithString:kOverlyAttachedGirlfriendURLString];
break;
case 1:
url = [NSURL URLWithString:kSuccessKidURLString];
break;
case 2:
url = [NSURL URLWithString:kLotsOfFacesURLString];
break;
default:
break;
}
dispatch_group_enter(downloadGroup); // 3
Photo *photo = [[Photo alloc] initwithURL:url
withCompletionBlock:^(UIImage *image, NSError *_error) {
if (_error) {
error = _error;
}
dispatch_group_leave(downloadGroup); // 4
}];
[[PhotoManager sharedManager] addPhoto:photo];
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
dispatch_async(dispatch_get_main_queue(), ^{ // 6
if (completionBlock) { // 7
completionBlock(error);
}
});
});
}
Second Implementation:
- (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
// 1
__block NSError *error;
dispatch_group_t downloadGroup = dispatch_group_create();
for (NSInteger i = 0; i < 3; i++) {
NSURL *url;
switch (i) {
case 0:
url = [NSURL URLWithString:kOverlyAttachedGirlfriendURLString];
break;
case 1:
url = [NSURL URLWithString:kSuccessKidURLString];
break;
case 2:
url = [NSURL URLWithString:kLotsOfFacesURLString];
break;
default:
break;
}
dispatch_group_enter(downloadGroup); // 2
Photo *photo = [[Photo alloc] initwithURL:url
withCompletionBlock:^(UIImage *image, NSError *_error) {
if (_error) {
error = _error;
}
dispatch_group_leave(downloadGroup); // 3
}];
[[PhotoManager sharedManager] addPhoto:photo];
}
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{ // 4
if (completionBlock) {
completionBlock(error);
}
});
}
I the first implementation the relevant code is surrounded with dispatch_async
and everything is super clear.
BUT, the second implementation is unclear! I don't get it, how the GCD
mechanism is taking any part beside of the notification for enter and leave?
Upvotes: 2
Views: 271
Reputation: 813
The first implementation runs a background thread starting at
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1
So the whole function runs there. But this background thread gets eventually blocked at this line (it waits for all the photos to be downloaded):
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER);
This is all fine since you are not blocking the main thread. But it is a bit of a clumsy implementation since,
dispatch_async
around the whole function.So the second implementation has two benefits:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{}
)dispatch_group_notify
serves as the asynchronous completion block.Upvotes: 2
Reputation: 52592
The first method is an asynchronous method. You can call it from any thread, including the main thread. It will perform actions in a background thread, and when it's done, it will dispatch the callback block on the main thread. A call to this method returns immediately, the callback will be called a lot later.
The second method is a blocking method. The method will not finish until the photos are downloaded, and then it calls your callback method. This method should most definitely not be called from the main thread, only from a background thread.
Upvotes: 0