Due to a weird request which I tried to turn down but it didn\'t work, I had to override the navigationBar\'s back Button.
I have made a custom UINavigationControlle
(My previous post was completely wrong. This is a complete rewrite with an appropriate solution.)
I had this behavior pop up when I chose to delete some code generating a warning when I was converting to ARC -- code that I thought was not being called.
Here's the situation:
If you shadow navigationBar:shouldPopItem:
in a subclass of UINavigationController, then the current view controller will NOT be popped when the user touches the NavBar's BACK button. However, if you call popViewControllerAnimated:
directly, your navigationBar:shouldPopItem:
will still be called, and the view controller will pop.
Here's why the view controller fails to pop when the user touches the BACK button:
UINavigationController has a hidden method called navigationBar:shouldPopItem:
. This method IS called when the user clicks the BACK button, and it is the method that normally calls popViewControllerAnimated:
when the user touches the BACK button.
When you shadow navigationBar:shouldPopItem:
, the super class' implementation is not called, and hence the ViewController is not popped.
Why you should NOT call popViewControllerAnimated:
within your subclass' navigationBar:shouldPopItem:
:
If you call popViewControllerAnimated:
within navigationBar:shouldPopItem:
, you will see the behavior that you desire when you click the BACK button on the NavBar: You can determine whether or not you want to pop, and your view controller pops if you want it to.
But, if you call popViewControllerAnimated:
directly, you will end up popping two view controllers: One from your direct call to popViewControllerAnimated:
, and one from the call you added to within navigationBar:shouldPopItem:
.
What I believe to be the safe solution:
Your custom nav controller should be declared like this:
@interface CustomNavigationController : UINavigationController
{
// .. any ivars you want
}
@end
Your implementation should contain code that looks something like this:
// Required to prevent a warning for the call [super navigationBar:navigationBar shouldPopItem:item]
@interface UINavigationController ()
@end
@implementation CustomNavigationController
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
BOOL rv = TRUE;
if ( /* some condition to determine should NOT pop */ )
{
// we won't pop
rv = FALSE;
// extra code you might want to execute ...
} else
{
// It's not documented that the super implements this method, so we're being safe
if ([[CustomNavigationController superclass]
instancesRespondToSelector:@selector(navigationBar:shouldPopItem:)])
{
// Allow the super class to do its thing, which includes popping the view controller
rv = [super navigationBar:navigationBar shouldPopItem:item];
}
}
return rv;
}