84 votes

Comment puis-je faire éclater une vue d'un UINavigationController et la remplacer par une autre en une seule opération ?

J'ai une application où je dois supprimer une vue de la pile d'un UINavigationController et la remplacer par une autre. La situation est que la première vue crée un élément éditable puis se remplace par un éditeur pour l'élément. Lorsque je fais la solution évidente dans la première vue:

MyEditViewController *mevc = [[MYEditViewController alloc] initWithGizmo: gizmo];

[self retain];
[self.navigationController popViewControllerAnimated: NO];
[self.navigationController pushViewController: mevc animated: YES];
[self release];

Je rencontre un comportement très étrange. En général, la vue de l'éditeur apparaîtra, mais si j'essaie d'utiliser le bouton précédent de la barre de navigation, j'obtiens des écrans supplémentaires, certains vides, et certains juste gâchés. Le titre devient aléatoire aussi. C'est comme si la pile de navigation était complètement corrompue.

Quelle serait une meilleure approche pour ce problème?

Merci, Matt

1voto

bbrame Points 2643

Ma façon préférée de le faire est avec une catégorie sur UINavigationController. Ce qui suit devrait fonctionner:

UINavigationController+Helpers.h #import

@interface UINavigationController (Helpers)

- (UIViewController*) replaceTopViewControllerWithViewController: (UIViewController*) controller;

@end

UINavigationController+Helpers.m

import "UINavigationController+Helpers.h"

@implementation UINavigationController (Helpers)

- (UIViewController*) replaceTopViewControllerWithViewController: (UIViewController*) controller {
    UIViewController* topController = self.viewControllers.lastObject;
    [[topController retain] autorelease];
    UIViewController* poppedViewController = [self popViewControllerAnimated:NO];
    [self pushViewController:controller animated:NO];
    return poppedViewController;
}

@end

Ensuite, depuis votre contrôleur de vue, vous pouvez remplacer la vue supérieure par une nouvelle de cette manière:

[self.navigationController replaceTopViewControllerWithViewController: newController];

0voto

jignesh Points 41

Vous pouvez vérifier avec le tableau de contrôleurs de navigation qui vous donnera tous les contrôleurs de vue que vous avez ajoutés dans la pile de navigation. En utilisant ce tableau, vous pouvez naviguer en arrière vers un contrôleur de vue spécifique.

0voto

MOM Points 41

Pour monotouch / xamarin IOS :

à l'intérieur de la classe UISplitViewController ;

UINavigationController mainNav = this._navController;
//List controllers = mainNav.ViewControllers.ToList();
mainNav.ViewControllers = new UIViewController[] {};
mainNav.PushViewController(detail, true);//pour avoir l'animation

0voto

payliu Points 138

En outre,

Vous pouvez utiliser category pour éviter que self.navigationController ne devienne nil après popViewControllerAnimated

simplement pop et push, c'est facile à comprendre, pas besoin d'accéder à viewControllers....

// UINavigationController+Helper.h
@interface UINavigationController (Helper)

- (UIViewController*) popThenPushViewController:(UIViewController *)viewController animated:(BOOL)animated;

@end

// UINavigationController+Helper.m
@implementation UINavigationController (Helper)

- (UIViewController*) popThenPushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    UIViewController *v =[self popViewControllerAnimated:NO];

    [self pushViewController:viewController animated:animated];

    return v;
}
@end

Dans votre ViewController

// #import "UINavigationController+Helper.h"
// invoquer dans votre code
UIViewController *v= [[MyNewViewController alloc] init();

[self.navigationController popThenPushViewController:v animated:YES];

RELEASE_SAFELY(v);

0voto

alasker Points 56

Pas exactement la réponse mais pourrait être utile dans certains scénarios (le mien par exemple):

Si vous avez besoin de faire apparaître le contrôleur de vue C et d'aller à B (hors de la pile) au lieu de A (celui en dessous de C), il est possible de pousser B avant C, et d'avoir les 3 sur la pile. En gardant la poussée de B invisible, et en choisissant de faire apparaître uniquement C ou bien C et B ensemble, vous pouvez obtenir le même effet.

problème initial A -> C (je veux faire apparaître C et montrer B, hors de la pile)

solution possible A -> B (poussé invisible) -> C (quand je fais apparaître C, je choisis de montrer B ou bien de le faire apparaître aussi)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X