iphone - example - ¿Cómo subclasificar UINavigationBar para un UINavigationController mediante programación?
navigation controller swift 4 example (6)
Estoy usando una función personalizada drawRect para dibujar en UINavigationBar
en mi aplicación en iOS4, no usa imágenes, solo CoreGraphics.
Dado que no puede implementar drawRect en la categoría UINavigationBar en iOS5, Apple está sugiriendo la subclase UINavigationBar
.
¿Cómo es posible reemplazar UINavigationBar
con mi subclase en UINavigationController
(para que sea compatible con iOS4 y iOS5) cuando la propiedad navigationBar
es de solo lectura?
@property(nonatomic, readonly) UINavigationBar *navigationBar
No estoy usando XIB en mi aplicación en absoluto, por lo que agregar una UINavigationBar
a una NIB y cambiar la clase a través de InterfaceBuilder no es una opción.
A partir de iOS6, esto es ahora bastante sencillo de lograr sin tener que mezclar o mezclar con otras clases utilizando el método initWithNavigationBarClass:toolbarClass:
- (id)initWithNavigationBarClass:(Class)navigationBarClass
toolbarClass:(Class)toolbarClass;
De la documentación:
Inicializa y devuelve un controlador de navegación recién creado que usa sus subclases de barra personalizadas
Respuesta actualizada para iOS6.
En iOS 6, agregaron un nuevo método a UINavigationController
que también está disponible de manera retractiva en iOS 5:
- (id)initWithNavigationBarClass:(Class)navigationBarClass
toolbarClass:(Class)toolbarClass;
Ahora puede pasar su clase personalizada cuando se crea una instancia del controlador de navegación.
La única forma compatible de hacer esto en iOS 4 es usar el método Interface Builder. No tiene que usar IB para hacer nada, excepto establecer la subclase UINavigationBar (aún puede hacer toda su configuración de vista programáticamente).
Tuvo problemas con las respuestas 2-4 en iOS 4 (de la respuesta de AnswerBot), y necesitaba una forma de cargar el UINavigationController programáticamente (aunque el método NIB funcionó) ... Así que hice esto:
Creó un archivo XIB en blanco (no establezca el propietario del archivo), agregue un UINavigationController (déle su clase personalizada de UINavigationController), cambie UINavigationBar a su clase personalizada (aquí está CustomNavigationBar), luego cree el siguiente encabezado de clase personalizado (CustomNavigationController.h en este caso):
#import <UIKit/UIKit.h>
@interface CustomNavigationController : UINavigationController
+ (CustomNavigationController *)navigationController;
+ (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController;
@end
e implementación personalizada (CustomNavigationController.mm)
#import "CustomNavigationController.h"
@interface CustomNavigationController ()
@end
@implementation CustomNavigationController
+ (CustomNavigationController *)navigationController
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomNavigationController" owner:self options:nil];
CustomNavigationController *controller = (CustomNavigationController *)[nib objectAtIndex:0];
return controller;
}
+ (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController
{
CustomNavigationController *controller = [CustomNavigationController navigationController];
[controller setViewControllers:[NSArray arrayWithObject:rootViewController]];
return controller;
}
- (id)init
{
self = [super init];
[self autorelease]; // We are ditching the one they allocated. Need to load from NIB.
return [[CustomNavigationController navigationController] retain]; // Over-retain, this should be alloced
}
- (id)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super init];
[self autorelease];
return [[CustomNavigationController navigationControllerWithRootViewController:rootViewController] retain];
}
@end
Luego puedes iniciar esa clase en lugar de un UINavigationController y tendrás tu barra de navegación personalizada. Si desea hacerlo en un xib, cambie la clase de UINavigationController y UINavigationBar dentro de su XIB.
Una especie de enmienda a las respuestas anteriores para aquellos que todavía quieren usar initWithRootViewController
. Subclase UINavigationController
y luego:
- (id) initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil];
if (self)
{
self.viewControllers = [NSArray arrayWithObjects:rootViewController, nil];
}
return self;
}
- (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass;
Me enfrenté a un problema con el método anterior. Hay un método "initWithRootViewController" para inicializar UINavigationController. Pero, si uso "initWithNavigationBarClass" para iniciar el UINavigationController, entonces no hay forma de que pueda establecer "rootViewController" para el UINavigationController.
Este enlace Cambiar el rootViewController de un UINavigationController me ayudó a agregar un rootViewController después de que el UINavigationController se inicializa con "initWithNavigationBarClass". Básicamente, el truco es subclase UINavigationController. Aunque no lo he probado en IB todavía, pero está funcionando bien en el código.