Search code examples
iosanimationios7uinavigationcontroller

popViewController while pushViewController is animating resulting in corrupted navigation bar


I have a situation in my app where a navigation controller pushViewController:animated:YES is triggered by a user. The user can also trigger a popViewController:animated:YES by tapping another control. The intent is that the popViewController is the undo or inverse of the pushViewController.

However, if the user triggers the popViewController:animated:YES while the pushViewController animation is still happening, I get a message logged to the console:

2014-08-22 08:26:36.601 MyApp[22380:60b] nested pop animation can result in corrupted    navigation bar
2014-08-22 08:26:36.960 MyApp[22380:60b] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

And indeed, the navigation bar does get corrupted: the back button is no longer visible. I have to go do something else then come back to the affected page in my app to get it working properly again.

What can I do to avoid this race condition? My first thought was protect the popViewController call with a check to see if a current navigation animation is already occurring, and waiting for that to finish (or even canceling the popViewController call completely). However, I haven't been able to find a way of detecting that an action is already occurring.


Solution

  • There are two solutions to this problem. I suggest you to implement first one.

    1 . Avoid user interaction on multiple controls at a time by setting exclusive touch to them.

    • Set exclusiveTouch property to YES for those controls if they shares superView(parent view) else you will have to set this property YES to their parent views.

    2 . Implement UINavigationControllerDelegate protocol in that view controller where user is tapping multiple controls at a time.

     – navigationController:willShowViewController:animated:
     – navigationController:didShowViewController:animated:
    

    Set a flag when first delegate method gets called & reset it in second. Use this flag on every push/pop operation.