How to detect when UINavigationController animation has finished?

I hope this is a simple question. If I have a UINavigationController and I push a new view controller onto the stack with an animated transition, how can I detect when the animation has finished and the new view controller is on screen?

I have a few scenarios where I need to push a new controller that then has to do a long-running operation. I'd like to push the new view first so there's something on screen before I start blocking the main thread for a long time. If I do the push immediately followed by my long-running task the view won't show up until after both are done of course and the main thread is able to process events again.

So, what I'd like to do be able to detect in the new controller once the animation is done and the view is on screen, and then start the task.

Answers


+1 to @DHamrick's recommendation for not blocking the main thread at all.

To answer the original question, you can detect viewController changes in two places:

  1. The viewController you just pushed will receive viewWillAppear: and viewDidAppear: messages. If you want to know when a specific viewController appears, implement these methods.

  2. The navigationController:didShowViewController:animated: method mentioned by @Mike Z is sent to the navigationController's delegate. You will need to assign an object to be that delegate in order to receive this message. You will then know every time a viewController appears.


Instead of blocking the main thread, you should look in to doing your long running operation inside of another thread or even better, using a GCD queue.

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, NULL);
dispatch_async(backgroundQueue, ^{
    // Do your long running code
    dispatch_async(dispatch_get_main_queue(), ^{
        //Update your UI
    });
});

You can put this code in your viewDidLoad: so that you know your UI has already loaded. This also means you don't have to rely on the timing of the animation.


I haven't tested or implemented this myself, but the documentation sounds like:

navigationController:didShowViewController:animated:

Described as: Sent to the receiver just after the navigation controller displays a view controller’s view and navigation item properties.

Otherwise,

setAnimationDidStopSelector: might be something that would work for you.

Described as: Sets the message to send to the animation delegate when animation stops.


Need Your Help

UICollectionView cellForItemAtIndexPath not registering cell

objective-c ios xcode ipad uicollectionview

I am trying to use UICollectionViewCell, since all I want to display is an image. I can add the image to the cell using UIColor colorWithImage: on the UICollectionViewCell's contentView property.