Reputation: 4844
I have several dispatch_async
methods linked so they authenticate a user in my system.
The next async method only happens when the previous one finishes, as they each have completion handlers.
When the last one is finished I perform a custom segue with 2 uiview
animation blocks.
However, when I log when each of these actually run, there is a considerable gap between the log and the animation actually happening, eventually the views animate and the completion block is called.
I don't really know how useful it would be adding my code here, but i have tested and it must be the async methods because if I comment them out and just return YES
the animations happen without delay at the same time as the log.
Does anyone know why this might happen?
EDIT *(with code)
Typical 'exist check' used for email, user, user id.
- (void)existsInSystemWithCompletionHandler:(void (^)(BOOL))block
{
self.existsInSystem = NO;
if (self.isValid) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//
// Get data
//
if (dataIsValid) {
block(YES);
} else {
block(NO);
}
});
} else {
block(self.existsInSystem);
}
}
Check user exists
[potentialUser existsInSystemWithCompletionHandler:^(BOOL success) {
if (success) {
// Perform segue
//
[self performSegueWithIdentifier:@"Logging In" sender:self];
}
}];
Segue
- (void)perform
{
NSLog(@"Perform");
LogInViewController *sourceViewController = (LogInViewController *)self.sourceViewController;
LoggingInViewController *destinationViewController = (LoggingInViewController *)self.destinationViewController;
destinationViewController.user = sourceViewController.potentialUser;
// Animate
//
[UIView animateWithDuration:0.2f
animations:^{
NSLog(@"Animation 1");
//
// Animate blah blah blah
//
}];
[UIView animateWithDuration:0.4f
delay:0.0f
options:UIViewAnimationOptionCurveEaseIn
animations:^{
NSLog(@"Animation 2");
//
// Animate blah blah blah
//
}
completion:^(BOOL finished) {
NSLog(@"Completion");
//
// Finished
//
[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
}];
}
LoggingIn VC
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.user loginWithCompletionHandler:^(BOOL success) {
if (success) {
[self performSegueWithIdentifier:@"Logged In" sender:self];
}
}];
}
Upvotes: 0
Views: 581
Reputation: 4844
Fixed! It seems to work now that in my code I have added the lines:
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(success);
});
Upvotes: 1
Reputation: 80265
From your description it seems likely that your segue is waiting for a process to finish.
Maybe your nested async methods that follow each other through their completion methods have produced somewhat convoluted code. This might be the reason why you could be overlooking the blocking method.
One way to tidy up your code is use a sequential queue. The blocks pushed to the queue will start only when the previous one has finished.
Upvotes: 0