iOS中navigationController的后退buttoncallback
我将视图推到了导航控制器上,当我按下后退button时,它会自动转到上一个视图。 我想在按下返回button之前做一些事情,然后将视图从堆栈popup。 哪个是后退buttoncallback函数?
William Jockusch的答案用简单的方法解决了这个问题。
-(void) viewWillDisappear:(BOOL)animated { if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) { // back button was pressed. We know this is true because self is no longer // in the navigation stack. } [super viewWillDisappear:animated]; }
在我看来是最好的解决scheme。
- (void)didMoveToParentViewController:(UIViewController *)parent { if (![parent isEqual:self.parentViewController]) { NSLog(@"Back pressed"); } }
但它只适用于iOS5 +
重写后退button可能会更好,所以您可以在视图popup之前处理事件,例如用户确认。
在viewDidLoad创build一个UIBarButtonItem并设置self.navigationItem.leftBarButtonItem它传入一个select
- (void) viewDidLoad { // change the back button to cancel and add an event handler UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@”back” style:UIBarButtonItemStyleBordered target:self action:@selector(handleBack:)]; self.navigationItem.leftBarButtonItem = backButton; [backButton release]; } - (void) handleBack:(id)sender { // pop to root view controller [self.navigationController popToRootViewControllerAnimated:YES]; }
然后你可以做一些事情,比如提出一个UIAlertView来确认动作,然后popup视图控制器等。
或者不是创build一个新的后退button,您可以遵循UINavigationController委托方法来按下后退button时执行操作。
我结束了这个解决scheme。 当我们点击返回buttonviewDidDisappear的方法调用。 我们可以通过调用isMovingFromParentViewControllerselect器来检查哪一个返回true。 我们可以传回数据(使用委托).hope这个帮助某人。
-(void)viewDidDisappear:(BOOL)animated{ if (self.isMovingToParentViewController) { } if (self.isMovingFromParentViewController) { //moving back //pass to viewCollection delegate and update UI [self.delegateObject passBackSavedData:self.dataModel]; } }
对于“在popup视图之前”:
- (void)willMoveToParentViewController:(UIViewController *)parent{ if (parent == nil){ NSLog(@"do whatever you want here"); } }
有一个比问询viewControllers更合适的方法。 您可以让您的控制器成为具有后退button的导航条的代表。 这是一个例子。 在你想要处理按下后退button的控制器的实现中,告诉它它将实现UINavigationBarDelegate协议:
@interface MyViewController () <UINavigationBarDelegate>
然后在你的初始化代码中的某处(可能在viewDidLoad中)使你的控制器成为其导航栏的代表:
self.navigationController.navigationBar.delegate = self;
最后,实现shouldPopItem方法。 当后退button被按下时,这个方法被调用。 如果在堆栈中有多个控制器或导航项目,则可能需要检查哪些导航项目正在popup(项目参数),以便在您希望的时候只执行自定义内容。 这是一个例子:
-(BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { NSLog(@"Back button got pressed!"); //if you return NO, the back button press is cancelled return YES; }
这是检测这个的正确方法。
- (void)willMoveToParentViewController:(UIViewController *)parent{ if (parent == nil){ //do stuff } }
这个方法在视图被推入的时候被调用。 所以检查parent == nil是从栈中popup视图控制器
如果您不能使用“viewWillDisappear”或类似的方法,请尝试子类UINavigationController。 这是头类:
#import <Foundation/Foundation.h> @class MyViewController; @interface CCNavigationController : UINavigationController @property (nonatomic, strong) MyViewController *viewController; @end
实现类:
#import "CCNavigationController.h" #import "MyViewController.h" @implementation CCNavigationController { } - (UIViewController *)popViewControllerAnimated:(BOOL)animated { @"This is the moment for you to do whatever you want" [self.viewController doCustomMethod]; return [super popViewControllerAnimated:animated]; } @end
另一方面,您需要将此viewController链接到您的自定义NavigationController,因此,在您的viewDidLoad方法中,您的常规viewController执行以下操作:
@implementation MyViewController { - (void)viewDidLoad { [super viewDidLoad]; ((CCNavigationController*)self.navigationController).viewController = self; } }
下面是我实现的另一种方式(没有用unwind segue来testing,但可能不会像其他人所说的那样,在这个页面上的其他解决scheme)使父视图控制器在子VC推入之前执行操作从视图堆栈中popup(我使用了这个从原来的UINavigationController开始的几个级别)。 这也可以用来在childVC被推动之前执行操作。 这具有使用iOS系统后退button的附加优点,而不必创build自定义的UIBarButtonItem或UIButton。
-
让你的父VC采用
UINavigationControllerDelegate
协议并注册委托消息:MyParentViewController : UIViewController <UINavigationControllerDelegate> -(void)viewDidLoad { self.navigationcontroller.delegate = self; }
-
在
MyParentViewController
实现这个UINavigationControllerDelegate
实例方法:- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { // Test if operation is a pop; can also test for a push (ie, do something before the ChildVC is pushed if (operation == UINavigationControllerOperationPop) { // Make sure it's the child class you're looking for if ([fromVC isKindOfClass:[ChildViewController class]]) { // Can handle logic here or send to another method; can also access all properties of child VC at this time return [self didPressBackButtonOnChildViewControllerVC:fromVC]; } } // If you don't want to specify a nav controller transition return nil; }
-
如果在上面的
UINavigationControllerDelegate
实例方法中指定了特定的callback函数-(id <UIViewControllerAnimatedTransitioning>)didPressBackButtonOnAddSearchRegionsVC:(UIViewController *)fromVC { ChildViewController *childVC = ChildViewController.new; childVC = (ChildViewController *)fromVC; // childVC.propertiesIWantToAccess go here // If you don't want to specify a nav controller transition return nil;
}
如果你正在使用一个Storyboard,并且你是从一个push segue来的,你也可以重写shouldPerformSegueWithIdentifier:sender: