I have those methods to retrieve some object information from the internet:
- (void)downloadAppInfo:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableHosts:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableServices:(void(^)())success
failure:(void(^)(NSError *error))failure;
- (void)getAvailableActions:(void(^)())success
failure:(void(^)(NSError *error))failure;
The downloaded stuff gets stored in object properties, so that is why the success functions return nothing.
Now, I want to have one method like this:
- (void)syncEverything:(void(^)())success
failure:(void(^)(NSError *error))failure;
Which does nothing else than calling all the methods above, and returning only after every single method has performed its success or failure block.
How can I do this?
Hint: I am aware that cascading the methods calls in each others success block would work. But this is neither 'clean' nor helpful when later implementations include further methods.
Attempts:
I tried running each of the calls in an NSOperation
and adding those NSOperations
to an NSOperationQueue
followed by a "completion operation" which depends on every one of the preceding operations.
This won't work. Since the operations are considered completed even before their respective success/failure blocks return.
I also tried using dispatch_group
. But it is not clear to me wether I am doing it the right way. Unfortunately, it is not working.
You were almost there, the problem is most likely to be that those methods are asynchronous, so you need an extra synchronization step. Just try with the following fix:
for(Appliance *appliance in _mutAppliances) {
dispatch_group_async(
group,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t sem = dispatch_semaphore_create( 0 );
NSLog(@"Block START");
[appliance downloadAppInfo:^{
NSLog(@"Block SUCCESS");
dispatch_semaphore_signal(sem);
}
failure:^(NSError *error){
NSLog(@"Block FAILURE");
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"Block END");
});
dispatch_group_notify(
group,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
NSLog(@"FINAL block");
success();
});
}