J'ai besoin d'effectuer certaines actions lorsque le bouton de retour (retour à l'écran précédent, retour à la vue parent) est enfoncé sur une barre de navigation.
Existe-t-il une méthode que je peux mettre en œuvre pour capturer l'événement et déclencher des actions pour mettre en pause et enregistrer les données avant que l'écran ne disparaisse?
iphone
objective-c
ios
xcode
ewok
la source
la source
Réponses:
MISE À JOUR: Selon certains commentaires, la solution de la réponse originale ne semble pas fonctionner dans certains scénarios sous iOS 8+. Je ne peux pas vérifier que c'est effectivement le cas sans plus de détails.
Pour ceux d'entre vous, cependant, dans cette situation, il existe une alternative. Détecter le moment où un contrôleur de vue est en cours de saut est possible par remplacement
willMove(toParentViewController:)
. L'idée de base est qu'un contrôleur de vue est affiché quandparent
estnil
.Consultez «Implémentation d'un contrôleur de vue de conteneur» pour plus de détails.
Depuis iOS 5, j'ai trouvé que le moyen le plus simple de gérer cette situation consiste à utiliser la nouvelle méthode
- (BOOL)isMovingFromParentViewController
:- (BOOL)isMovingFromParentViewController
est logique lorsque vous poussez et sautez des contrôleurs dans une pile de navigation.Cependant, si vous présentez des contrôleurs de vue modale, vous devez utiliser à la
- (BOOL)isBeingDismissed
place:Comme indiqué dans cette question , vous pouvez combiner les deux propriétés:
D'autres solutions reposent sur l'existence d'un
UINavigationBar
. Au lieu de cela, j'aime davantage mon approche car elle dissocie les tâches requises à effectuer de l'action qui a déclenché l'événement, c'est-à-dire en appuyant sur un bouton de retour.la source
self.isMovingFromParentViewController
a une valeur TRUE lorsque je fais apparaître la pile de navigation par programmation en utilisantpopToRootViewControllerAnimated
- sans aucune pression sur le bouton de retour. Dois-je décliner votre réponse? (le sujet dit que "le bouton" retour "est pressé sur une barre de navigation")override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController(){ println("back button pressed") } }
-viewDidDisappear:
car il est possible que vous obteniez un-viewWillDisappear:
sans a-viewDidDisappear:
(comme lorsque vous commencez à faire glisser pour ignorer un élément du contrôleur de navigation, puis à annuler ce balayage.Alors que
viewWillAppear()
etviewDidDisappear()
sont appelés lorsque le bouton de retour est appuyé, ils sont également appelés à d'autres moments. Voir la fin de la réponse pour en savoir plus.Utilisation de UIViewController.parent
Il est préférable de détecter le bouton de retour lorsque le VC est supprimé de son parent (le NavigationController) à l'aide de
willMoveToParentViewController(_:)
OUdidMoveToParentViewController()
Si parent est nul, le contrôleur de vue est sorti de la pile de navigation et rejeté. Si le parent n'est pas nul, il est ajouté à la pile et présenté.
Swap sur
willMove
pourdidMove
et le contrôle self.parent pour faire le travail après le contrôleur de vue est rejeté.Arrêter le licenciement
Notez que la vérification du parent ne vous permet pas de "suspendre" la transition si vous devez faire une sorte de sauvegarde asynchrone. Pour ce faire, vous pouvez implémenter ce qui suit. Le seul inconvénient ici est que vous perdez le bouton de retour de style / animé iOS. Faites également attention ici avec le geste de balayage interactif. Utilisez ce qui suit pour gérer ce cas.
Plus sur la vue apparaîtra / est apparu
Si vous n'avez pas rencontré le
viewWillAppear
viewDidDisappear
problème, passons en revue un exemple. Supposons que vous ayez trois contrôleurs de vue:Permet de suivre les appels au
detailVC
fur et à mesure que vous passez delistVC
àsettingsVC
et de retour àlistVC
Liste> Détail (push detailVC)
Detail.viewDidAppear
<- apparaîtDetail> Settings (push settingsVC)
Detail.viewDidDisappear
<- disparaîtEt comme nous revenons en arrière ...
Paramètres> Détail (pop settingsVC)
Detail.viewDidAppear
<- apparaissentDétails> Liste (pop detailVC)
Detail.viewDidDisappear
<- disparaissentRemarquez qu'il
viewDidDisappear
est appelé plusieurs fois, non seulement lors du retour, mais également lors de la progression. Pour une opération rapide qui peut être souhaitée, mais pour une opération plus complexe comme un appel réseau à enregistrer, ce n'est peut-être pas le cas.la source
didMoveToParantViewController:
doit travailler lorsque la vue n'est plus visible. Utile pour iOS7 avec le interactiveGesutre_ = self.navigationController?.popViewController(animated: true)
, il n'est donc pas simplement appelé lors d'une pression sur le bouton Retour. Je recherche un appel qui ne fonctionne que lorsque vous appuyez sur Retour.Première méthode
Deuxième méthode
la source
Ceux qui prétendent que cela ne fonctionne pas se trompent:
Cela fonctionne très bien. Alors qu'est-ce qui cause le mythe répandu selon lequel ce n'est pas le cas?
Le problème semble être dû à une implémentation incorrecte d'une méthode différente , à savoir que l'implémentation de a
willMove(toParent:)
oublié d'appelersuper
.Si vous implémentez
willMove(toParent:)
sans appelersuper
, alorsself.isMovingFromParent
serafalse
et l'utilisation deviewWillDisappear
semblera échouer. Cela n'a pas échoué; tu l'as cassé.REMARQUE: Le vrai problème est généralement le deuxième contrôleur de vue détectant que le premier contrôleur de vue a été sauté. S'il vous plaît voir aussi la discussion plus générale ici: Unified UIViewController "est devenu le premier" détection?
EDIT Un commentaire suggère que cela devrait être
viewDidDisappear
plutôt queviewWillDisappear
.la source
true
pour le geste de balayage interactif - à partir du bord gauche du contrôleur de vue - même si le balayage ne l'a pas complètement fait. Donc, au lieu de l'enregistrerwillDisappear
, faites-le endidDisappear
travaux.Je joue (ou me bats) avec ce problème depuis deux jours. IMO, la meilleure approche consiste simplement à créer une classe d'extension et un protocole, comme ceci:
Cela fonctionne parce
UINavigationController
que recevra un appel ànavigationBar:shouldPopItem:
chaque fois qu'un contrôleur de vue est sauté. Là, nous détectons si le dos a été enfoncé ou non (tout autre bouton). La seule chose que vous devez faire est d'implémenter le protocole dans le contrôleur de vue où back est pressé.N'oubliez pas de faire apparaître manuellement le contrôleur de vue à l'intérieur
backButtonPressedSel
, si tout va bien.Si vous avez déjà sous-classé
UINavigationViewController
et implémenté,navigationBar:shouldPopItem:
ne vous inquiétez pas, cela n'interférera pas avec cela.Vous pourriez également être intéressé par la désactivation du geste du dos.
la source
Cela fonctionne pour moi dans iOS 9.3.x avec Swift:
Contrairement à d'autres solutions ici, cela ne semble pas se déclencher de manière inattendue.
la source
Pour mémoire, je pense que c'est plus ce qu'il cherchait…
la source
Comme
purrrminator
dit, la réponseelitalon
n'est pas tout à fait correcte, car elleyour stuff
serait exécutée même lors du saut du contrôleur par programme.La solution que j'ai trouvée jusqu'à présent n'est pas très sympa, mais cela fonctionne pour moi. En plus de ce qui a été
elitalon
dit, je vérifie également si je suis programmé ou non:Vous devez ajouter cette propriété à votre contrôleur et la définir sur OUI avant de sauter par programme:
Merci de votre aide!
la source
La meilleure façon est d'utiliser les méthodes de délégué UINavigationController
En utilisant cela, vous pouvez savoir quel contrôleur affiche le UINavigationController.
la source
J'ai résolu ce problème en ajoutant un UIControl à la barre de navigation sur le côté gauche.
Et vous devez vous rappeler de le supprimer lorsque la vue disparaîtra:
C'est tout!
la source
Vous pouvez utiliser le rappel du bouton retour, comme ceci:
pour la version rapide, vous pouvez faire quelque chose comme dans une portée globale
En dessous de celui-ci, vous placez dans le viewcontroller où vous souhaitez contrôler l'action du bouton retour:
la source
navigationShouldPopOnBackButton
vient-il? Il ne fait pas partie de l'API publique.Comme l'a dit Coli88, vous devriez vérifier le protocole UINavigationBarDelegate.
De manière plus générale, vous pouvez également utiliser
- (void)viewWillDisapear:(BOOL)animated
pour effectuer un travail personnalisé lorsque la vue conservée par le contrôleur de vue actuellement visible est sur le point de disparaître. Malheureusement, cela couvrirait les problèmes de poussée et de pop.la source
Pour Swift avec un UINavigationController:
la source
La réponse de 7ynk3r était très proche de ce que j'ai utilisé à la fin, mais il fallait quelques ajustements:
la source
Vous devriez vérifier le protocole UINavigationBarDelegate . Dans ce cas, vous souhaiterez peut-être utiliser la méthode navigationBar: shouldPopItem:.
la source
self.navigationController.isMovingFromParentViewController ne fonctionne plus sur iOS8 et 9 j'utilise:
la source
(RAPIDE)
solution finalement trouvée .. la méthode que nous recherchions est "willShowViewController" qui est la méthode déléguée de UINavigationController
la source
MyViewController
àPushedController
.