iOS中的navigationController中的后退按钮回调

问题描述:

我已将视图推到导航控制器上,当我按下后退按钮时,它会自动转到上一个视图。我想在按下返回按钮之前做一些事情,然后将视图从堆栈弹出。哪个是后退按钮回调函数?iOS中的navigationController中的后退按钮回调

+0

[导航控制器的后退按钮设置动作]的可能重复(HTTP:/ /*.com/questions/1214965/setting-action-for-back-button-in-navigation-controller) – Zakaria 2013-03-05 06:52:33

+0

结帐此[溶液] [1],其保留的返回按钮式为好。 [1]:http://*.com/a/29943156/3839641 – Sarasranglt 2015-04-29 12:06:00

William Jockusch的answer用简单的方法解决了这个问题。

-(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]; 
} 
+26

不仅当用户敲击后退按钮,但在每一个事件的视图被弹出,执行该代码(例如,具有在完成时或保存按钮在右侧)。 – 2013-04-25 19:34:35

+6

或者当前进到新视图时。 – GuybrushThreepwood 2013-12-02 10:00:21

+0

当用户从左边缘移动时(InteractivePopGestureRecognizer),也会调用此方法。在我的情况下,我特别在寻找用户何时按下而不从左边缘平移。 – 2014-03-20 00:11:24

它可能更好地覆盖后退按钮使您可以处理之前的观点被弹出的东西,如用户确认的情况下

在viewDidLoad中创建的UIBarButtonItem,并设置self.navigationItem.leftBarButtonItem它在SEL通过

- (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中确认操作,然后弹出视图控制器等

或者不是创建一个新的后退按钮,您可以遵循UINavigationController委托方法在按下后退按钮时执行操作。

+0

'UINavigationControllerDelegate'没有方法在点击后退按钮时被调用。 – 2013-04-25 19:37:07

+0

该技术允许验证视图控制器的数据并从导航控制器的后退按钮进行条件返回。 – gjpc 2013-08-20 00:20:48

+0

此解决方案打破了iOS 7+的边缘滑动功能 – 2015-04-30 00:31:00

在我看来最好的解决方案。

- (void)didMoveToParentViewController:(UIViewController *)parent 
{ 
    if (![parent isEqual:self.parentViewController]) { 
     NSLog(@"Back pressed"); 
    } 
} 

但它仅与iOS5的+

+3

此技术无法区分后退按钮和退出滑动。 – smileBot 2014-06-27 18:25:08

+0

willMoveToParentViewController和viewWillDisappear方法没有解释控制器必须销毁,didMoveToParentViewController是正确的 – Henk 2015-09-22 05:36:38

工作如果您不能使用 “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; 
    } 
} 

还有比问问viewControllers更合适的方法。您可以让您的控制器成为具有后退按钮的导航条的代表。这是一个例子。在要处理后退按钮的按下,告诉它,它会实现UINavigationBarDelegate协议控制器的实现:

@interface MyViewController() <UINavigationBarDelegate> 

然后在某处你的初始化代码(可能是在viewDidLoad中)使您的控制器其导航栏的代表:

self.navigationController.navigationBar.delegate = self; 

最后,实施shouldPopItem方法。这个方法在按下后退按钮时被调用。如果您在堆栈中有多个控制器或导航项目,您可能需要检查哪些导航项目会弹出(项目参数),以便您只在预期时执行自定义内容。这里有一个例子:

-(BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item 
{ 
    NSLog(@"Back button got pressed!"); 
    //if you return NO, the back button press is cancelled 
    return YES; 
} 
+2

没有为我工作..因为它是瘦的。 “***终止应用程序由于未捕获的异常'NSInternalInconsistencyException',原因:'无法手动设置由控制器管理的UINavigationBar上的委托'。” – DynamicDan 2013-12-24 17:23:29

+0

这将不幸与UINavigationController无效,相反,您需要一个标准的UIViewController一个UINavigationBar在其中。这意味着你不能利用NavigationController为你提供的几个自动视图控制器。抱歉! – 2014-01-06 15:51:03

+0

我刚刚使用UINavigationBar而不是NavigationBarController,然后它工作正常。我知道问题是关于NavigationBarController,但这个解决方案是精简的。 – appsunited 2014-11-24 15:49:25

对于“弹出之前的观点,从堆栈”:

- (void)willMoveToParentViewController:(UIViewController *)parent{ 
    if (parent == nil){ 
     NSLog(@"do whatever you want here"); 
    } 
} 

如果您使用的是故事板,你就从推SEGUE来了,你也可以只覆写shouldPerformSegueWithIdentifier:sender:

这里的另一种方式我实现了(没带开卷赛格瑞测试,但它可能不会区分,因为人在这个网页上关于其他的解决方案已经说明)有父视图控制器之前执行操作它所推送的子VC会从视图堆栈中弹出(我使用这个从原始UINavigationController开始的几个级别)。这也可以用于在childVC被推动之前执行操作。这具有使用iOS系统后退按钮的额外优势,而不必创建自定义的UIBarButtonItem或UIButton。

  1. 您的父母VC采用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 (i.e., 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; 
    } 
    
  2. MyParentViewController : UIViewController <UINavigationControllerDelegate> 
    
    -(void)viewDidLoad { 
        self.navigationcontroller.delegate = self; 
    } 
    
  3. MyParentViewController实现此UINavigationControllerDelegate实例方法在上面的回调函数UINavigationControllerDelegate实例方法

    -(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; 
    

    }

我结束了这个解决方案。当我们点击按钮viewDidDisappear方法调用。我们可以通过调用isMovingFromParentViewController选择器来检查哪个返回true。我们可以将数据传回(使用委托).hop这可以帮助某人。

-(void)viewDidDisappear:(BOOL)animated{ 

    if (self.isMovingToParentViewController) { 

    } 
    if (self.isMovingFromParentViewController) { 
     //moving back 
     //pass to viewCollection delegate and update UI 
     [self.delegateObject passBackSavedData:self.dataModel]; 

    } 
} 
+0

不要忘记'[超级viewDidDisappear:动画]' – SamB 2017-09-27 22:45:25

这是为了检测这种正确的方法。

- (void)willMoveToParentViewController:(UIViewController *)parent{ 
    if (parent == nil){ 
     //do stuff 

    } 
} 

当推送视图时也会调用此方法。所以,检查父==零是从堆栈

弹出视图控制器这是我的作品在斯威夫特:

override func viewWillDisappear(_ animated: Bool) { 
    if self.navigationController?.viewControllers.index(of: self) == nil { 
     // back button pressed or back gesture performed 
    } 

    super.viewWillDisappear(animated) 
}