Question

UINavigationController's documentation contains no pushViewController methods with a completion: parameter.

Was it helpful?

Solution 6

I would go with @justMartin's answer . But below is another approach.

push animation take 0.3 seconds.So, if you want to run some function here after completion use performSelector after 0.3 seconds of delay.

[self performSelector:@selector(completedPushing:) withObject:nil afterDelay:.3];

OR
After pushing the new viewController onto navigation stack,the old viewController view is removed from view hierarchy.so this results in call of viewDidDisappear on old ViewController.You can write your completion code there. don't forget to call super at some point of implementation of viewDidDisappear.

OTHER TIPS

The better solution would be wrapping the push animation by an CATransaction and set the completionBlock. There's no need to deal with timings.

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    //whatever you want to do after the push
}];
[[self navigationController] pushViewController:viewController animated:YES];
[CATransaction commit];

justMartin's answer worked great for me. For those new to using swift API:

CATransaction.begin()
navigationController?.pushViewController(viewController, animated: true)
CATransaction.setCompletionBlock({ 
    //your post animation logic
})
CATransaction.commit()

Solution with CATransaction is great but there is another way to do that. You can make your controller a delegate of UINavigationController and implement didShowViewController method:

class FooBarController: UIViewController, UINavigationControllerDelegate {
  func viewDidLoad() {
    self.navigationController?.delegate = self
  }

  func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
    // your awesome completion code here 
  }
}

This approach can be more convenient for your task

Not sure if I understand correctly, but I pushed a view controller in a completion block as follows. In a table view controller, added the following line to the header file:

typedef void(^myCompletion)(BOOL);

Then in the class itself, added the following method:

-(void) myMethod:(myCompletion) compblock
{
    compblock(YES);
}

Now in didSelectRowAtIndexPath, I called myMethod and in the completion block, pushed a view controller.

[self myMethod:^(BOOL finished) {
    if(finished){
        dispatch_async(dispatch_get_main_queue(), ^{
            DVSecondTableViewController *vc = [[DVSecondTableViewController alloc] init];
            [self.navigationController pushViewController:vc animated:YES];
        });
    }
}];

I'm not sure if it's okay to push view controllers outside of the main thread, so I embedded that call in a dispatch_async().

Try using -[UIViewControllerTransitionCoordinator animateAlongsideTransitionInView:animation:completion:]:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (!self.isPushing) {
        self.pushing = YES;
        [super pushViewController:viewController animated:animated];
        if (!self.transitionCoordinator) {
            self.pushing = NO;
        } else {
            [self.transitionCoordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
                self.pushing = NO;
            }];
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top