How to add a completion handler block for when I pop UIViewController?

by

Today I pondered about a problem which I had overlooked in past. How to add a completion handler block for when I pop UIViewController?


navigationController?.popViewController(animated: true)

In modal transition, dismissViewControllerAnimated, apple offers an option to call a completion block when dismissal of modal is finished. This is quite handy for various situations where you need to perform certain task like signalling a delegate about something when controller is removed from top of navigation or window.


dismiss(animated: true) {
}

Something similar isn’t offered directly in api for pop and push transitions. We do have been provided with viewDidAppear like methods that may be used to get things certain way. Flexibility and easiness that comes from completion handler of transition is unbeaten.

What we don’t have available from api can be solved by using core animation’s transactions. We group multiple animation related changes together and ensure all changes are run at the same time.

This is fine but how to notify when animation changes are finished?

CATransaction enables to create completion block which no matter the numbers of animation change is running or various combination of animation timings, completion block will be called when all animation changes has finishing performing.


CATransaction.setCompletionBlock({
    // Every animation added to this transaction is now finished
})



Let’s create an extension to UINavigationController and implement the method that takes the closure to perform our completion handler which gets called when our transition is finished within CATransaction queue.


extension UINavigationController {
    func popViewControllerWithHandler(animated:Bool = true, completion: @escaping ()->()) {
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)
        self.popViewController(animated: animated)
        CATransaction.commit()
    }

    func pushViewController(viewController: UIViewController, animated:Bool = true,  completion: @escaping ()->()) {
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)
        self.pushViewController(viewController, animated: animated)
        CATransaction.commit()
    }
}

Now we use below to pop and push our UIViewController and have completion handler:


navigationController?.popViewControllerWithHandler(animated: true, completion: {
                        
})

navigationController?.pushViewController(viewController: controller, animated: true, completion: {

})

You might also like: How to add a custom section header to a table view in Swift

You might also like: How to Send Local Video to iMessage in Swift

You might also like: AVAudioPlayer not playing any sound

You might also like: How to Get Substring With NSRange in Swift 5

You might also like: Adding two numbers in macOS x86-64 Assembly - Part 2

More Articles

Recommended posts