Quelqu'un sait-il comment puis-je utiliser ma sous-classe personnalisée de UINavigationBar
si j'instancie par UINavigationController
programme (sans IB)?
Faites glisser un UINavigationController
dans IB, montrez-moi un sous la barre de navigation et en utilisant Identity Inspectory, je peux changer le type de classe et définir ma propre sous-classe deUINavigationBar
mais par programmation je ne peux pas, la navigationBar
propriété de Navigation Controller est en lecture seule ...
Que dois-je faire pour personnaliser la barre de navigation par programme? IB est-il plus "puissant" que "code"? Je pensais que tout ce qui pouvait être fait à l'IB pouvait l'être également par programmation.
Réponses:
Vous n'avez pas besoin de jouer avec le XIB, utilisez simplement KVC.
la source
Depuis iOS5, Apple fournit une méthode pour le faire directement. Référence
la source
À partir d'iOS 4, vous pouvez utiliser la
UINib
classe pour résoudre ce problème.UINavigationBar
sous-classe personnalisée .UINavigationController
comme objet unique.UINavigationController
'sUINavigationBar
sur votre sous-classe personnalisée.[navController setViewcontrollers[NSArray arrayWithObject:myRootVC]];
[navController pushViewController:myRootVC];
Dans du code:
Vous avez maintenant un
UINavigationController
avec votre coutumeUINavigationBar
.la source
Pour autant que je sache, il est parfois en effet nécessaire de sous-classer UINavigationBar, de faire un restyling non standard. Il est parfois possible d'éviter d'avoir à le faire en utilisant des catégories , mais pas toujours.
Actuellement, pour autant que je sache, le seul moyen de définir une UINavigationBar personnalisée dans un UIViewController est via IB (c'est-à-dire via une archive) - cela ne devrait probablement pas être ainsi, mais pour l'instant, nous devons vivre avec.
C'est souvent bien, mais parfois utiliser IB n'est pas vraiment faisable.
Donc, j'ai vu trois options:
L'option 1 était irréalisable (ou du moins trop ennuyeuse) pour moi dans ce cas, car je devais créer le UINavigationController par programme, 2 est un peu dangereuse et plutôt une option de dernier recours à mon avis, j'ai donc choisi l'option 3.
Mon approche consistait à créer une archive `` modèle '' d'un UINavigationController et à la désarchiver, en la renvoyant dans
initWithRootViewController
.Voici comment:
Dans IB, j'ai créé un UINavigationController avec l'ensemble de classes approprié pour UINavigationBar.
Ensuite, j'ai pris le contrôleur existant et en ai enregistré une copie archivée à l'aide de
+[NSKeyedArchiver archiveRootObject:toFile:]
. Je viens de faire cela dans le délégué de l'application, dans le simulateur.J'ai ensuite utilisé l'utilitaire 'xxd' avec l'indicateur -i, pour générer du code c à partir du fichier enregistré, pour intégrer la version archivée dans ma sous-classe (
xxd -i path/to/file
).Dans
initWithRootViewController
je désarchive ce modèle et je me fixe au résultat de la désarchivage:Ensuite, je peux simplement récupérer une nouvelle instance de ma sous-classe UIViewController qui a la barre de navigation personnalisée définie:
Cela me donne 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'avais pas besoin de faire de remplacement de méthode légèrement désagréable, et je n'ai pas à me soucier des plumes quand je veux vraiment travailler de manière programmatique.
Je voudrais voir l'équivalent de
+layerClass
dans UINavigationController -+navigationBarClass
- mais pour l'instant, cela fonctionne.la source
J'utilise "option 1"
Créez un fichier nib contenant uniquement le UINavigationController. Et définissez la classe UINavigationBar sur ma classe personnalisée.
la source
La solution de Michael fonctionne, mais vous pouvez éviter NSKeyedArchiver et l'utilitaire «xxd». Sous-classez simplement UINavigationController et remplacez
initWithRootViewController
, en chargeant directement votre NIB NavigationController personnalisé:la source
Mise à jour: l' utilisation
object_SetClass()
ne fonctionne plus comme si iOS5 GM. Une solution alternative a été ajoutée ci-dessous.Utilisez NSKeyedUnarchiver pour définir manuellement la classe de désarchivage de la barre de navigation.
Remarque: cette solution originale ne fonctionne que pré-iOS5:
Il existe une excellente solution, que j'ai publiée ici - injectez la sous-classe navBar directement dans votre vue
UINavigationController
:la source
Un scénario que j'ai trouvé que nous devons utiliser la sous-classe plutôt que la catégorie consiste à définir la couleur d'arrière-plan de la barre de navigation avec l'image du motif, car dans iOS5, l'écrasement de drawRect en utilisant la catégorie ne fonctionne plus. Si vous souhaitez prendre en charge ios3.1-5.0, la seule façon de le faire est de sous-classer la barre de navigation.
la source
Ces méthodes de catégorie sont dangereuses et ne conviennent pas aux novices. De plus, la complication avec iOS4 et iOS5 étant différents, en fait un domaine qui peut causer des bogues pour de nombreuses personnes. Voici une sous-classe simple que j'utilise qui prend en charge iOS4.0 ~ iOS6.0 et qui est très simple.
.h
.m
la source
Il n'est pas recommandé de sous-
UINavigationBar
classer la classe. La meilleure façon de personnaliser la barre de navigation est de définir ses propriétés pour la faire apparaître comme vous le souhaitez et d'utiliser des vues personnalisées dans UIBarButtonItems avec un délégué pour obtenir le comportement souhaité.Qu'essayez-vous de faire qui nécessite un sous-classement?
De plus, je ne pense pas qu'IB remplace réellement la barre de navigation. Je suis presque sûr qu'il n'affiche tout simplement pas celui par défaut et que votre barre de navigation personnalisée est une sous-vue. Si vous appelez UINavigationController.navigationBar, obtenez-vous une instance de votre barre?
la source
Si vous voulez sous-classer navBar juste pour changer l'image d'arrière-plan - ce n'est pas nécessaire dans iOS 5. Il y aura une méthode comme celle-ci setBackgroundImage
la source
setBackgroundImage:forBarMetrics:
comme décrit ici: developer.apple.com/library/IOS/#documentation/UIKit/Reference/…Suite au commentaire de obb64, j'ai fini par utiliser son astuce avec
setViewControllers:animated:
pour définir le contrôleur commerootController
pour lenavigationController
chargé à partir de la pointe. Voici le code que j'utilise:la source