Completion block for popViewController Completion block for popViewController ios ios

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()    }}