I need to synchronize a bunch of information from my RestAPI. I have to make 6 RestAPI calls to shut down. I developed API calls with blocks and returned an NSError, if any. 3 of these calls must be nested because the first call provides information to others and allows you to make, while the other 3 calls can be made independently. Due to improved network performance, I designed my synchronization request as follows:
- 1 NSBlockOperation, which contains the first nested 3 blocks;
- 1 NSBlockOperation, which contains the other three blocks;
- 1 NSBlockOperation, which I use as "semphore", and tells me when everything works.
The last NSBlockOperation has a dependency on the previous two NSBlockOperation.
I also have an NSOperationQueue that contains all three NSBlockOperation, where the NSBlockOperation semaphore is added as the last in the queue. The result of what I would like to achieve: the first two blocks, called at the same time, and when their work ends, the NSBlockOperation semaphore is called and returns the controls to the user providing the UIAlertMessage.
The result is not explained earlier: controls are returned without waiting for the end of the syncAllBlocksInformation block.
Below is the code that contains NSBlockOperation:
-(void)syncAllBlocksInformation:(void(^)(NSError *error))completion{ __block NSError *blockError = nil; NSOperation *syncUserInfoOperation = [NSBlockOperation blockOperationWithBlock:^{ [dataSync syncUserInfo:tfMail.text password:tfPassword.text completion:^(NSError *error, NSNumber *idUser) { if(!error){ [dataSync syncUserfilesInfo:idUser completion:^(NSError *error) { if(!error){ [dataSync syncUserBookings:^(NSError *error) { if(error){ blockError = error; } }]; } else{ blockError = error; } }]; } else{ blockError = error; } }]; }]; NSBlockOperation *otherSyncOperations = [NSBlockOperation blockOperationWithBlock:^{ [dataSync syncNewsInfo:^(NSError *error) { if(error){ blockError = error; NSLog(@"error %@",error); } }]; }]; [otherSyncOperations addExecutionBlock:^{ [dataSync syncLocationsInfo:^(NSError *error) { if(error){ blockError = error; NSLog(@"error %@",error); } }]; }]; [otherSyncOperations addExecutionBlock:^{ [dataSync syncExoticAnimalTypesAndAnimals:^(NSError *error) { if(error){ blockError = error; NSLog(@"error %@",error); } }]; }]; NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"END"); }]; [completionOperation setCompletionBlock:^{ NSLog(@"Syc isEx %i",syncUserInfoOperation.isExecuting); NSLog(@"other isEx %i",otherSyncOperations.isExecuting); completion(blockError); }]; NSOperationQueue *opQueue = [NSOperationQueue new]; [completionOperation addDependency:syncUserInfoOperation]; [completionOperation addDependency:otherSyncOperations]; [opQueue addOperation:syncUserInfoOperation]; [opQueue addOperation:otherSyncOperations]; [opQueue addOperation:completionOperation]; }
And here is the code that calls above the block:
-(IBAction)login:(id)sender{ [self dismissKeyboardOpened:nil]; hud=[MBProgressHUD showHUDAddedTo:self.view animated:YES]; [hud setLabelText:NSLocalizedString(@"login_hud_message", login_hud_message )]; [hud setMode:MBProgressHUDModeIndeterminate]; [self showHudAndNetworkActivity:YES]; [self syncAllBlocksInformation:^(NSError *error) { [self showHudAndNetworkActivity:NO]; if(!error){ NSLog(@"End LOGIN"); [self showAlert:@"Login" message:@"Login OK" dismiss:YES]; } else{ [self showAlert:@"Error" message:@"Login NO" dismiss:NO]; } }]; }
What's wrong?
source share