J'essaie de remplacer l'action par défaut du bouton de retour dans un contrôleur de navigation. J'ai fourni une cible une action sur le bouton personnalisé. La chose étrange est que lorsque vous l'assignez via l'attribut backbutton, il ne leur prête pas attention et affiche simplement la vue actuelle et retourne à la racine:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
Dès que je le place via le leftBarButtonItem
sur, navigationItem
il appelle mon action, mais le bouton ressemble à un bouton rond au lieu de celui avec une flèche vers l'arrière:
self.navigationItem.leftBarButtonItem = backButton;
Comment puis-je lui faire appeler mon action personnalisée avant de revenir à la vue racine? Existe-t-il un moyen de remplacer l'action de retour par défaut, ou existe-t-il une méthode qui est toujours appelée lorsque vous quittez une vue ( viewDidUnload
ne le fait pas)?
Réponses:
Essayez de placer ceci dans le contrôleur de vue où vous souhaitez détecter la presse:
la source
if (find(self.navigationController!.viewControllers as! [UIViewController],self)==nil)
J'ai implémenté l' extension UIViewController-BackButtonHandler . Il n'a pas besoin de sous-classer quoi que ce soit, il suffit de le mettre dans votre projet et de remplacer la
navigationShouldPopOnBackButton
méthode dans laUIViewController
classe:Téléchargez un exemple d'application .
la source
navigationBar:shouldPopItem:
n'est pas une méthode privée car elle fait partie duUINavigationBarDelegate
protocole.YES
)? ou le fera-t-il dans le futur? le sous-classement est probablement une option plus sûreNO
le bouton de retour reste dans un état désactivé (visuellement, car il reçoit et réagit toujours aux événements tactiles). Je l'ai contourné en ajoutant uneelse
déclaration à lashouldPop
vérification et en parcourant les sous-vues de la barre de navigation, et en remettant laalpha
valeur à 1 si nécessaire dans un bloc d'animation: gist.github.com/idevsoftware/9754057Contrairement à Amagrammer dit, c'est possible. Vous devez sous-classer votre
navigationController
. J'ai tout expliqué ici (y compris le code d'exemple).la source
Version Swift:
(sur https://stackoverflow.com/a/19132881/826435 )
Dans votre contrôleur de vue, vous vous conformez simplement à un protocole et effectuez toute action dont vous avez besoin:
Ensuite, créez une classe, par exemple
NavigationController+BackButton
, et copiez-collez simplement le code ci-dessous:la source
shouldPopOnBackButtonPress
devrait être appelé tant qu'il n'y a pas de bogues.performSomeActionOnThePressOfABackButton
est juste une méthode inventée qui n'existe pas.performSomeActionOnThePressOfABackButton
dans mon contrôleur pour exécuter une action spécifique lorsque le bouton de retour est enfoncé, mais cette méthode n'a jamais été appelée, l'action est un retour normalUINavigationController
, lenavigationBar.delegate
est défini sur le contrôleur de navigation. Donc, les méthodes DEVRAIENT être appelées. Cependant, dans Swift, je ne peux pas les faire appeler, même dans une sous-classe. Cependant, je les ai fait appeler en Objective-C, donc j'utiliserais simplement la version Objective-C pour le moment. Peut-être un bug Swift.Ce n'est pas possible de le faire directement. Il existe plusieurs alternatives:
UIBarButtonItem
qui valide au toucher et apparaît si le test réussitUITextField
méthode déléguée, telle que-textFieldShouldReturn:
, qui est appelée après avoir appuyé sur le boutonReturn
ouDone
du clavierL'inconvénient de la première option est que le style de flèche pointant vers la gauche du bouton Précédent n'est pas accessible à partir d'un bouton de barre personnalisé. Vous devez donc utiliser une image ou utiliser un bouton de style normal.
La deuxième option est intéressante car vous récupérez le champ de texte dans la méthode de délégué, vous pouvez donc cibler votre logique de validation sur le champ de texte spécifique envoyé à la méthode de rappel du délégué.
la source
Pour certaines raisons de threading, la solution mentionnée par @HansPinckaers ne me convenait pas, mais j'ai trouvé un moyen très plus simple d'attraper un toucher sur le bouton de retour, et je veux épingler ceci ici au cas où cela pourrait éviter des heures de tromperies pour quelqu'un d'autre. L'astuce est vraiment simple: ajoutez simplement un UIButton transparent en tant que sous-vue à votre UINavigationBar, et définissez vos sélecteurs pour lui comme s'il s'agissait du vrai bouton! Voici un exemple utilisant Monotouch et C #, mais la traduction en objective-c ne devrait pas être trop difficile à trouver.
Fait amusant: à des fins de test et pour trouver de bonnes dimensions pour mon faux bouton, j'ai mis sa couleur de fond au bleu ... Et ça se voit derrière le bouton de retour! Quoi qu'il en soit, il attrape toujours tout contact ciblant le bouton d'origine.
la source
Cette technique vous permet de changer le texte du bouton "retour" sans affecter le titre de l'un des contrôleurs de vue ou voir le texte du bouton retour changer pendant l'animation.
Ajoutez ceci à la méthode init dans le contrôleur de vue appelant :
la source
Le moyen le plus simple
Vous pouvez utiliser les méthodes de délégation de UINavigationController. La méthode
willShowViewController
est appelée lorsque vous appuyez sur le bouton de retour de votre VC.Faites ce que vous voulez lorsque vous appuyez sur de retourla source
Voici ma solution Swift. Dans votre sous-classe de UIViewController, remplacez la méthode navigationShouldPopOnBackButton.
la source
Nous avons trouvé une solution qui conserve également le style du bouton de retour. Ajoutez la méthode suivante à votre contrôleur de vue.
Maintenant, fournissez une fonctionnalité au besoin dans la méthode suivante:
Tout ce qu'il fait est de couvrir le bouton arrière avec un bouton transparent;)
la source
========================================
S'appuyant sur les réponses précédentes avec UIAlert en Swift5 dans une Asynchronous manière
Sur votre manette
la source
Je ne crois pas que ce soit possible, facilement. La seule façon que je pense de contourner cela est de créer votre propre image de flèche du bouton de retour à placer là-haut. C'était frustrant pour moi au début mais je vois pourquoi, par souci de cohérence, il a été laissé de côté.
Vous pouvez vous rapprocher (sans la flèche) en créant un bouton normal et en masquant le bouton de retour par défaut:
la source
Il existe un moyen plus simple en sous-classant simplement la méthode déléguée de
UINavigationBar
et en remplaçant laShouldPopItem
méthode .la source
La solution de onegray n'est pas sûre.Selon les documents officiels d'Apple, https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html , nous devrions éviter de faire cela.
"Si le nom d'une méthode déclarée dans une catégorie est le même qu'une méthode dans la classe d'origine, ou une méthode dans une autre catégorie sur la même classe (ou même une superclasse), le comportement n'est pas défini quant à l'implémentation de méthode utilisée au moment de l'exécution. Cela risque moins de poser problème si vous utilisez des catégories avec vos propres classes, mais peut entraîner des problèmes lors de l'utilisation de catégories pour ajouter des méthodes à des classes Cocoa ou Cocoa Touch standard. "
la source
Utilisation de Swift:
la source
Voici la version Swift 3 de la réponse de @oneway pour capturer l'événement du bouton de retour de la barre de navigation avant qu'il ne soit déclenché. Comme
UINavigationBarDelegate
ne peut pas être utilisé pourUIViewController
, vous devez créer un délégué qui sera déclenché lors de l'navigationBar
shouldPop
appel.Et puis, dans votre contrôleur de vue, ajoutez la fonction de délégué:
J'ai réalisé que nous voulions souvent ajouter un contrôleur d'alerte pour que les utilisateurs décident s'ils veulent revenir en arrière. Si oui, vous pouvez toujours
return false
ennavigationShouldPopOnBackButton()
fonction et fermer votre contrôleur de vue en faisant quelque chose comme ceci:la source
Value of type 'UIViewController' has no member 'navigationShouldPopOnBackButton'
lorsque j'essaye de compiler votre code, pour la ligneif vc.responds(to: #selector(v...
Aussi, leself.topViewController
retourne une option et il y a un avertissement pour cela aussi.let vc = self.topViewController as! MyViewController
et cela semble fonctionner correctement jusqu'à présent. Si vous pensez que c'est une bonne modification, vous pouvez modifier le code. Aussi, si vous pensez que cela ne devrait pas être fait, je serai heureux de savoir pourquoi. Merci pour ce code. Vous devriez probablement écrire un article de blog à ce sujet, car cette réponse est enterrée selon les votes.MyViewController
peut-être pas conformeBackButtonDelegate
. Plutôt que de forcer le déballage, vous devez le faireguard let vc = self.topViewController as? MyViewController else { return true }
pour éviter un éventuel crash.guard let vc = self.topViewController as? MyViewController else { self.popViewController(animated: true) return true }
s'assurer que l'écran se déplace vers la bonne page au cas où il ne peut pas être correctement diffusé. Je comprends maintenant que lanavigationBar
fonction est appelée dans tous les VC et pas seulement dans le viewcontroller où ce code existe. Peut-être sera-t-il également bon de mettre à jour le code dans votre réponse? Merci.Version de Swift 4 iOS 11.3:
Cela s'appuie sur la réponse de kgaidis de https://stackoverflow.com/a/34343418/4316579
Je ne sais pas quand l'extension a cessé de fonctionner, mais au moment d'écrire ces lignes (Swift 4), il semble que l'extension ne sera plus exécutée à moins que vous ne déclariez la conformité UINavigationBarDelegate comme décrit ci-dessous.
J'espère que cela aidera les gens qui se demandent pourquoi leur extension ne fonctionne plus.
la source
En utilisant les variables de cible et d'action que vous laissez actuellement «nil», vous devriez être en mesure de câbler vos boîtes de dialogue de sauvegarde afin qu'elles soient appelées lorsque le bouton est «sélectionné». Attention, cela peut se déclencher à des moments étranges.
Je suis principalement d'accord avec Amagrammer, mais je ne pense pas qu'il serait si difficile de personnaliser le bouton avec la flèche. Je voudrais simplement renommer le bouton de retour, prendre une capture d'écran, photoshop de la taille du bouton nécessaire et avoir cette image en haut de votre bouton.
la source
Vous pouvez essayer d'accéder à l'élément Bouton droit de NavigationBars et définir sa propriété de sélecteur ... voici une référence UIBarButtonItem de référence , une autre chose si cela ne fonctionne pas, définissez l'élément du bouton droit de la barre de navigation sur un UIBarButtonItem personnalisé que vous créer et définir son sélecteur ... j'espère que cela vous aidera
la source
Pour un formulaire qui nécessite une entrée utilisateur comme celui-ci, je recommanderais de l'invoquer en tant que "modal" au lieu de faire partie de votre pile de navigation. De cette façon, ils doivent s'occuper des affaires sur le formulaire, puis vous pouvez le valider et le rejeter à l'aide d'un bouton personnalisé. Vous pouvez même concevoir une barre de navigation qui ressemble au reste de votre application mais vous donne plus de contrôle.
la source
Pour intercepter le bouton Retour, couvrez-le simplement avec un UIControl transparent et interceptez les touches.
la source
Au moins dans Xcode 5, il existe une solution simple et plutôt bonne (pas parfaite). Dans IB, faites glisser un élément de bouton de barre hors du volet Utilitaires et déposez-le sur le côté gauche de la barre de navigation à l'endroit où se trouverait le bouton Précédent. Définissez le libellé sur "Retour". Vous aurez un bouton fonctionnel que vous pourrez lier à votre IBAction et fermer votre viewController. Je fais du travail puis je déclenche une séquence de déroulement et cela fonctionne parfaitement.
Ce qui n'est pas idéal, c'est que ce bouton n'obtient pas la flèche <et ne reporte pas le titre précédent des VC, mais je pense que cela peut être géré. Pour mes besoins, j'ai défini le nouveau bouton Retour pour être un bouton "Terminé" afin que son objectif soit clair.
Vous vous retrouvez également avec deux boutons Retour dans le navigateur IB, mais il est assez facile de l'étiqueter pour plus de clarté.
la source
Rapide
la source
Cette approche a fonctionné pour moi (mais le bouton "Retour" n'aura pas le signe "<"):
la source
Version rapide de la réponse de @ onegray
Maintenant, dans n'importe quel contrôleur, conformez-vous simplement à
RequestsNavigationPopVerification
et ce comportement est adopté par défaut.la source
Utilisation
isMovingFromParentViewController
la source
viewDidDisappear
. De cette façon, il ne se déclenchera qu'une fois que la vue aura définitivement disparu.La réponse de @William est correcte cependant, si l'utilisateur lance un geste de balayage pour revenir en arrière, la
viewWillDisappear
méthode est appelée et neself
sera même pas dans la pile de navigation (c'est-à-direself.navigationController.viewControllers
qu'elle ne contiendra pasself
), même si le balayage n'est pas terminé et le contrôleur de vue n'est pas réellement ouvert. Ainsi, la solution serait de:Désactivez le geste de balayage pour revenir en arrière
viewDidAppear
et autorisez uniquement l'utilisation du bouton de retour en utilisant:Ou utilisez simplement à la
viewDidDisappear
place, comme suit:la source
La solution que j'ai trouvée jusqu'à présent n'est pas très sympa, mais cela fonctionne pour moi. Prenant cette réponse , 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:
la source
Trouvé une nouvelle façon de le faire:
Objectif c
Rapide
la source