5 votes

UINavigationBar topItem/items semble s'ouvrir deux fois à l'arrière

Je gère ma propre UINavigationBar. J'ai besoin de le faire à cause d'un skinning important. La documentation relative à UINavigationController signale qu'il existe des limites à l'habillage de l'UINavigationBar lorsqu'elle est utilisée avec un UINavigationController.

J'ai mis en place un logging complet et d'après tout ce que je peux dire, le fait d'appuyer sur le bouton "Back" dans le UINavigationController fait sortir deux éléments de la pile au lieu d'un. J'obtiens un rappel de délégué unique qui me dit qu'il supprime l'élément logique, mais il supprime en fait cet élément et un autre.

L'élément ajouté au UINavigationController dans awakeFromNib doit jamais être supprimée. Il est en train d'être supprimé pour une raison quelconque.

Deux questions similaires se posent, mais aucune n'a de réponse satisfaisante. Ces deux questions sont les suivantes :

L'accesseur UINavigationBar .items ne renvoie pas l'UINavigationItem courant

UINavigationBar semble retirer 2 éléments de la pile lors d'un "retour"

- (void)awakeFromNib {
    [headerView setDelegate: self];
    [headerView pushNavigationItem: tableDisplay animated: NO];
}

- (void) selectedStory: (NSNotification *)not {
    [headerView pushNavigationItem: base animated: NO];
    NSLog(@"Selected story: %@", base);
}

- (void) baseNav {
    NSLog(@"Current items: %@", [headerView items]);
    BaseInnerItem *current = (BaseInnerItem *)[headerView topItem];
    [self addSubview: [current view]];
}

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPushItem: (UINavigationItem *)item {
    return YES;
}

- (BOOL)navigationBar: (UINavigationBar *)navigationBar shouldPopItem: (UINavigationItem *)item {
    return YES;
}

- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item {
    NSLog(@"didPushItem: %@", item);
    [self baseNav];
}

- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item {
    NSLog(@"didPopItem: %@", item);
    [self baseNav];
}

Modifié pour ajouter un débogage pertinent à partir d'une seule exécution :

2010-10-13 02:12:45.911 Remix2[17037:207] didPushItem: <TableDisplay: 0x5d41cc0>
2010-10-13 02:12:45.912 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>"
)
2010-10-13 02:12:49.020 Remix2[17037:207] didPushItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:49.021 Remix2[17037:207] Current items: (
    "<TableDisplay: 0x5d41cc0>",
    "<WebDisplay: 0x591a590>"
)
2010-10-13 02:12:49.023 Remix2[17037:207] Selected story: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.498 Remix2[17037:207] didPopItem: <WebDisplay: 0x591a590>
2010-10-13 02:12:59.499 Remix2[17037:207] Current items: (
)

0voto

LucasTizma Points 5452

Vous devez toujours appeler [super awakeFromNib] lorsque votre sous-classe implémente cette méthode, conformément à la documentation relative à la méthode -awakeFromNib :

Vous devez appeler la super implémentation de awakeFromNib pour donner aux classes mères la possibilité d'effectuer toute initialisation supplémentaire dont elles ont besoin

Cependant, il est important de noter que ...

Je ne comprends pas pourquoi il faut gérer sa propre barre de navigation. Si vous sous-classez UINavigationBar et de ne surcharger que certaines méthodes de dessin ou de mise en page telles que -drawRect: , -layoutSubviews etc., alors toute la logique derrière la gestion de la barre de navigation dans un contrôleur de navigation retombera simplement sur l'élément d'origine UINaviationBar classe.

J'ai dû procéder à une personnalisation poussée de l'affichage pour presque tous les grands projets de l'UE. UIKit mais j'ai toujours laissé la logique complexe aux classes d'origine, en ne surchargeant que les méthodes de dessin pour personnaliser l'aspect et la convivialité.

Par ailleurs, il est beaucoup plus facile d'habiller une application entière sans aucune sous-classe si tout ce que vous faites est d'utiliser des images personnalisées. En définissant la propriété contents vous pouvez soit personnaliser l'aspect et la convivialité d'une propriété UIView -Les cours sont dispensés en fonction des besoins ou pendant toute la durée de l'application :

#import <QuartzCore/QuartzCore.h>
...
- (void)viewDidLoad
{
    [super viewDidLoad];

    UIImage * navigationBarContents = [UIImage imageNamed:@"navigation-bar"];
    self.navigationController.navigationBar.layer.contents =    
        (id)navigationBarContents.CGImage;
}

Vous pouvez définir le contenu de toute classe qui hérite de UIView : barres de navigation, barres d'outils, boutons, etc. C'est beaucoup plus facile à gérer de cette manière, sans avoir à créer de sous-classe.

0voto

Nick Dowell Points 971

Il semble qu'il s'agisse d'un bogue dans la mise en œuvre de la fonction -[UINavigationBar items]

Lorsqu'il est appelé depuis l'intérieur de la -navigationBar:didPopItem: il omettra le dernier objet. Vous pouvez le vérifier en appelant [navigationBar valueForKey:@"_itemStack"] pour récupérer le tableau sous-jacent et vérifier que les éléments attendus sont toujours présents.

Ajouter un dispatch_async à l'intérieur -navigationBar:didPopItem: permet de contourner le problème dans mon application.

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