Custom action on Back Button UINavigationController
by Hans Pinckaers
Yes! There is a way of using the backBarButton with a custom action. No, it’s not by overriding the backBarButton property of navigationItem. This is not an ugly solution with images that simulate the “Back”-button (arrow-shaped.) It’s possible to use the backBarButton for popping the current viewController as normal, but than with other animations such as UIViewAnimationTransitionCurlDown.
Enough said, the solution is simple. You have to subclass your navigationController’s popViewControllerAnimated:(BOOL)animated. So create a custom navigationController:
customNavigationController.h
And a custom “popViewControllerAnimated:(BOOL)animated”, this popViewControllerAnimated-function uses the “UIViewAnimationTransitionCurlDown” when popping from a SettingsTableView.
customNavigationController.m
Use your custom navigationController in your appDelegate:
This code worked a treat. It’s so simple and obvious.
looks great, but I’m using xib. mmm…
Isn’t it possible to define your UINavigationController object in Interface Builder as a customNavigationController instance?
Ah got it working with the IB as mentioned above.
However, I’d like to ask the user if there sure they want to quit.
Don’t know how to do that. I tried commenting out the code within the IF block, but it keeps my current controller and shows the main controller title.
What should I do here ?
You could create a delegate method like “-(BOOL)navigationController:shouldPopViewController:”. Make your window the delegate. Return NO to that method. Display an UIAlertView and then pop again and return YES to that delegate method.
Could you provide an example of that ?
Yes, I will rewrite the article when I have time, providing the example.
[...] intercept the back button, I searched the net to find a solution. One of the top hits suggests subclassing UINavigationController and overriding – [UIViewController [...]
[...] 原文:Custom action on Back Button UINavigationController 分类: iPhone OS 标签: 评论 (0) Trackbacks (0) 发表评论 Trackback [...]
Excellent, clean and easy. Thx !
Simple and Perfect!
Tnk’s a lot!!!
You’re a genius! Thank you for the code and the details!
From Apple documentation “This (UINavigationController) class is not intended for subclassing. Instead, you use instances of it as-is in situations where you want your application’s user interface to reflect the hierarchical nature of your content.”
here is reference:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
so what could be another way of achieving this.
if([[self.viewControllers lastObject] class] == [SettingsTableController class])
should be written as
if([self.topViewController isMemberOfClass:[SettingsTableController class]])
To Jules or anyone else who happens upon this page: I also needed a “are you sure you want to quit?” on the back button for my app. Here’s how I implemented it. Tricky but possible!
Turns out if you implement the UINavigationBarDelegate in the CustomNavigationController, you can make use of the shouldPopItem method:
—————————————————-
CustomNavigationController.h :
#import
@interface CustomNavigationController : UINavigationController {
BOOL alertViewClicked;
BOOL regularPop;
}
@end
—————————————————-
CustomNavigationController.m :
#import “CustomNavigationController.h”
#import “SettingsTableController.h”
@implementation CustomNavigationController
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if (regularPop) {
regularPop = FALSE;
return YES;
}
if (alertViewClicked) {
alertViewClicked = FALSE;
return YES;
}
if ([self.topViewController isMemberOfClass:[SettingsTableViewController class]]) {
UIAlertView * exitAlert = [[[UIAlertView alloc] initWithTitle:@”Are you sure you want to quit?”
message:nil delegate:self cancelButtonTitle:@”Cancel” otherButtonTitles:@”Yes”, nil] autorelease];
[exitAlert show];
return NO;
}
else {
regularPop = TRUE;
[self popViewControllerAnimated:YES];
return NO;
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
//Cancel button
}
else if (buttonIndex == 1) {
//Yes button
alertViewClicked = TRUE;
[self popViewControllerAnimated:YES];
}
}
@end
—————————————————-
The weird logic with the “regularPop” bool is because for some reason just returning “YES” on shouldPopItem only pops the navbar, not the view associated with the navBar – for that to happen you have to directly call popViewControllerAnimated (which then calls shouldPopItem as part of its logic.)
you’re the best, for the second time.
Keep’em coming.
Great tip. Based on the suggestion of subclassing UINavigationController, I was able to very easily implement my own subclass, that allows me to conditionally call popToController:Animated: instead of popViewControllerAnimated. I added a property to my controller suclass, so that when set, I skip to the set viewController, rather than doing a normal pop.
This allows me to implement in-between views that act like menus in desktop apps, and then skip over those views as I pop the view off the stack that the user selected from the menu view. The look and feel is much better now, as the user doesn’t see the menu view ask I pop views.
Thanks to Hans .
@Ginny :your code is a perfect solution of my problem, thank you every much!