Retour bouton callback dans navigationController dans iOS

J'ai poussé une vue sur le contrôleur de navigation et lorsque j'appuie sur le bouton Retour, elle passe automatiquement à la vue précédente. Je veux faire quelques choses lorsque le bouton Retour est pressé avant d'éclater la vue de la pile. Quelle est la fonction de rappel du bouton Retour?

93
demandé sur Namratha 2011-03-07 12:36:23

11 réponses

Réponse de William Jockusch résolvez ce problème avec une astuce facile.

-(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];
}
158
répondu ymutlu 2017-05-23 12:02:37

, À mon avis la meilleure solution.

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

Mais cela ne fonctionne qu'avec iOS5 +

82
répondu Blank 2013-05-30 12:13:20

Il est probablement préférable de remplacer le backbutton afin que vous puissiez gérer l'événement avant que la vue ne soit affichée pour des choses telles que la confirmation de l'utilisateur.

Dans viewDidLoad créez un UIBarButtonItem et définissez self.navigationItem.leftBarButtonItem à lui en passant dans un 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];

}

Ensuite, vous pouvez faire des choses comme lever un UIAlertView pour confirmer l'action, puis pop le contrôleur de vue, etc.

Ou au lieu de créer un nouveau backbutton, vous pouvez UINavigationController déléguer des méthodes pour effectuer des actions lorsque le bouton de retour est pressé.

25
répondu roocell 2013-04-20 15:12:43

Je me retrouve avec cette solution. Comme nous tapons sur le bouton de retour viewDidDisappear méthode appelée. nous pouvons vérifier en appelant isMovingFromParentViewController selector qui renvoie true. nous pouvons renvoyer des données (en utilisant Delegate).espérons que cela aide quelqu'un.

-(void)viewDidDisappear:(BOOL)animated{

    if (self.isMovingToParentViewController) {

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

    }
}
8
répondu Avijit Nagare 2016-10-27 12:09:45

Pour "avant d'ouvrir la vue de la pile":

- (void)willMoveToParentViewController:(UIViewController *)parent{
    if (parent == nil){
        NSLog(@"do whatever you want here");
    }
}
7
répondu Anum Malik 2014-03-18 08:11:33

Il y a un moyen plus approprié que de demander aux viewControllers. Vous pouvez faire de votre contrôleur un délégué de la barre de navigation qui a le bouton Retour. Voici un exemple. Dans l'implémentation du contrôleur où vous voulez gérer la pression sur le bouton de retour, dites-lui qu'il implémentera le protocole UINavigationBarDelegate:

@interface MyViewController () <UINavigationBarDelegate>

Alors quelque part dans votre code d'initialisation (probablement dans viewDidLoad) faites de votre contrôleur le délégué de sa navigation bar:

self.navigationController.navigationBar.delegate = self;

Enfin, implémentez la méthode shouldPopItem. Cette méthode est appelée lorsque le bouton de retour est pressé. Si vous avez plusieurs contrôleurs ou éléments de navigation dans la pile, vous voudrez probablement vérifier lequel de ces éléments de navigation est sauté (le paramètre item), de sorte que vous ne faites vos choses personnalisées que lorsque vous vous y attendez. Voici un exemple:

-(BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
    NSLog(@"Back button got pressed!");
    //if you return NO, the back button press is cancelled
    return YES;
}
4
répondu Carlos Guzman 2013-11-10 05:30:13

C'est la bonne façon de détecter cela.

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

    }
}

Cette méthode est appelée lorsque view est également poussé. Donc, vérifier parent= = nil est pour éclater le contrôleur de vue de la pile

3
répondu Saad 2016-07-13 12:42:15

Si vous ne pouvez pas utiliser "viewWillDisappear" ou une méthode similaire, essayez de sous-classer UINavigationController. C'est la classe d'en-tête:

#import <Foundation/Foundation.h>
@class MyViewController;

@interface CCNavigationController : UINavigationController

@property (nonatomic, strong) MyViewController *viewController;

@end

Classe D'implémentation:

#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

D'autre part, vous devez lier ce viewController à votre NavigationController personnalisé, donc, dans votre méthode viewDidLoad pour votre ViewController régulier, faites ceci:

@implementation MyViewController {
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        ((CCNavigationController*)self.navigationController).viewController = self;
    }
}
2
répondu George Harley 2013-07-13 00:33:09

Voici une autre façon que j'ai implémentée (Je ne l'ai pas testée avec un segue de déroulement mais il ne se différencierait probablement pas, comme d'autres l'ont déclaré en ce qui concerne d'autres solutions sur cette page)pour que le contrôleur de vue parent effectue des actions avant que le VC enfant poussé ne sorte de la pile Cela pourrait également être utilisé pour effectuer des actions avant que childVC ne soit poussé. Cela a l'avantage de travailler avec le bouton de retour du système iOS, au lieu d'avoir à créer un UIBarButtonItem personnalisé ou UIButton.

  1. Demandez à votre parent VC d'adopter le protocole UINavigationControllerDelegate et inscrivez-vous pour les messages délégués:

    MyParentViewController : UIViewController <UINavigationControllerDelegate>
    
    -(void)viewDidLoad {
        self.navigationcontroller.delegate = self;
    }
    
  2. Implémentez cette méthode d'instance UINavigationControllerDelegate dans MyParentViewController:

    - (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;
    }
    
  3. Si vous spécifiez une fonction de rappel spécifique dans la méthode d'instance UINavigationControllerDelegate ci-dessus

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

    }

2
répondu Evan R 2014-06-30 01:29:10

Si vous utilisez un Storyboard et que vous venez d'un push segue, vous pouvez également remplacer shouldPerformSegueWithIdentifier:sender:.

0
répondu Mojo66 2014-04-09 13:10:47

C'est ce que cela fonctionne pour moi dans Swift:

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

    super.viewWillDisappear(animated)
}
0
répondu pableiros 2017-12-19 19:35:58