Adam Carter
Adam Carter

Reputation: 4844

Custom segue animating with delay after code being run. (Objective C)

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

Answers (2)

Adam Carter
Adam Carter

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

Mundi
Mundi

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

Related Questions