Pour autant que je sache, il est parfois nécessaire de sous-classer UINavigationBar pour effectuer un restylage non standard. Il est parfois possible d'éviter d'avoir à le faire en utilisant catégories mais pas toujours.
Actuellement, pour autant que je sache, le uniquement La façon de définir une UINavigationBar personnalisée au sein d'un UIViewController est via IB (c'est-à-dire via une archive) - il ne devrait probablement pas en être ainsi, mais pour l'instant, nous devons nous en accommoder.
C'est souvent très bien, mais il arrive que l'utilisation de l'IB ne soit pas vraiment possible.
Donc, j'ai vu trois options :
- Sous-classer UINavigationBar et accrocher tout ça dans IB, puis s'embêter à charger la nib chaque fois que je voulais un UINavigationController,
- Utilisez remplacement des méthodes dans une catégorie pour modifier le comportement de UINavigationBar, plutôt que de sous-classer, ou
- Sous-classez UINavigationBar et faites un peu de bricolage avec l'archivage/désarchivage de UINavigationController.
L'option 1 était irréalisable (ou du moins trop ennuyeuse) pour moi dans ce cas, car je devais créer le UINavigationController de manière programmatique, l'option 2 est un peu dangereuse et plus une option de dernier recours à mon avis, j'ai donc choisi l'option 3.
Mon approche a consisté à créer une archive "modèle" d'un UINavigationController, puis à la désarchiver, en la renvoyant dans le fichier initWithRootViewController
.
Voici comment :
Dans IB, j'ai créé un UINavigationController avec la classe appropriée définie pour la UINavigationBar.
Ensuite, j'ai pris le contrôleur existant, et j'en ai sauvegardé une copie archivée en utilisant +[NSKeyedArchiver archiveRootObject:toFile:]
. Je viens de le faire dans le délégué de l'application, dans le simulateur.
J'ai ensuite utilisé l'utilitaire 'xxd' avec le drapeau -i, pour générer du code c à partir du fichier sauvegardé, afin d'intégrer la version archivée dans ma sous-classe ( xxd -i path/to/file
).
Sur initWithRootViewController
Je désarchive ce modèle, et mets self au résultat de la désarchivage :
// This is the data from [NSKeyedArchiver archivedDataWithRootObject:controller], where
// controller is a CTNavigationController with navigation bar class set to CTNavigationBar,
// from IB. This c code was created using 'xxd -i'
static unsigned char archived_controller[] = {
0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd4, 0x01, 0x02, 0x03,
...
};
static unsigned int archived_controller_len = 682;
...
- (id)initWithRootViewController:(UIViewController *)rootViewController {
// Replace with unarchived view controller, necessary for the custom navigation bar
[self release];
self = (CTNavigationController*)[NSKeyedUnarchiver unarchiveObjectWithData:[NSData dataWithBytes:archived_controller length:archived_controller_len]];
[self setViewControllers:[NSArray arrayWithObject:rootViewController]];
return [self retain];
}
Ensuite, je peux simplement saisir une nouvelle instance de ma sous-classe UIViewController qui a la barre de navigation personnalisée définie :
UIViewController *modalViewController = [[[CTNavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[self.navigationController presentModalViewController:modalViewController animated:YES];
J'obtiens ainsi un UITableViewController modal avec une barre de navigation et une barre d'outils configurées, et avec la classe de barre de navigation personnalisée en place. Je n'ai pas eu besoin de procéder à un remplacement de méthode un peu méchant, et je n'ai pas à m'embêter avec des nibs lorsque je veux simplement travailler de manière programmatique.
J'aimerais voir l'équivalent de +layerClass
au sein de UINavigationController - +navigationBarClass
- mais pour l'instant, ça marche.
0 votes
Avez-vous eu la chance de trouver une solution ailleurs ?
0 votes
Avez-vous reçu une réponse à ce sujet ?