Completion block for popViewController
I know an answer has been accepted over two years ago, however this answer is incomplete.
There is no way to do what you're wanting out-of-the-box
This is technically correct because the UINavigationController
API doesn't offer any options for this. However by using the CoreAnimation framework it's possible to add a completion block to the underlying animation:
[CATransaction begin];[CATransaction setCompletionBlock:^{ // handle completion here}];[self.navigationController popViewControllerAnimated:YES];[CATransaction commit];
The completion block will be called as soon as the animation used by popViewControllerAnimated:
ends. This functionality has been available since iOS 4.
Swift 5 version - works like a charm. Based on this answer
extension UINavigationController { func pushViewController(viewController: UIViewController, animated: Bool, completion: () -> ()) { pushViewController(viewController, animated: animated) if let coordinator = transitionCoordinator() where animated { coordinator.animateAlongsideTransition(nil) { _ in completion() } } else { completion() } } func popViewController(animated: Bool, completion: () -> ()) { popViewControllerAnimated(animated) if let coordinator = transitionCoordinator() where animated { coordinator.animateAlongsideTransition(nil) { _ in completion() } } else { completion() } }}
I made a Swift
version with extensions with @JorisKluivers answer.
This will call a completion closure after the animation is done for both push
and pop
.
extension UINavigationController { func popViewControllerWithHandler(completion: ()->()) { CATransaction.begin() CATransaction.setCompletionBlock(completion) self.popViewControllerAnimated(true) CATransaction.commit() } func pushViewController(viewController: UIViewController, completion: ()->()) { CATransaction.begin() CATransaction.setCompletionBlock(completion) self.pushViewController(viewController, animated: true) CATransaction.commit() }}