Soweit ich das beurteilen kann, ist es manchmal tatsächlich notwendig, UINavigationBar zu unterordnen, um ein nicht standardmäßiges Restyling durchzuführen. Es ist manchmal möglich, dies zu vermeiden, indem Kategorien verwendet werden , aber nicht immer.
Derzeit, soweit ich weiß, die einzige Weg , um eine benutzerdefinierte UINavigationBar innerhalb eines UIViewController gesetzt ist über IB (das heißt, über ein Archiv) - es sollte wohl nicht so sein, aber für jetzt, wir müssen damit leben.
Dies ist oft in Ordnung, aber manchmal ist die Verwendung von IB nicht wirklich machbar.
Also sah ich drei Möglichkeiten:
- Unterklasse UINavigationBar und alles in IB einbinden, dann jedes Mal, wenn ich einen UINavigationController wollte, die Feder laden.
- Verwenden Sie den Methodenersatz innerhalb einer Kategorie, um das Verhalten von UINavigationBar anstelle von Unterklassen zu ändern, oder
- Unterklasse UINavigationBar und ein wenig herumspielen mit dem Archivieren / Aufheben der Archivierung des UINavigationControllers.
Option 1 war in diesem Fall für mich nicht durchführbar (oder zumindest zu ärgerlich), da ich den UINavigationController programmgesteuert erstellen musste. 2 ist meiner Meinung nach ein wenig gefährlich und eher ein letzter Ausweg, daher habe ich Option 3 gewählt.
Mein Ansatz war es, ein "Vorlagen" -Archiv eines UINavigationControllers zu erstellen und dieses zu archivieren und es zurückzugeben initWithRootViewController
.
Hier ist wie:
In IB habe ich einen UINavigationController mit der entsprechenden Klasse für die UINavigationBar erstellt.
Dann nahm ich den vorhandenen Controller und speicherte eine archivierte Kopie davon mit +[NSKeyedArchiver archiveRootObject:toFile:]
. Ich habe dies gerade innerhalb des App-Delegaten im Simulator getan.
Ich habe dann das Dienstprogramm 'xxd' mit dem Flag -i verwendet, um C-Code aus der gespeicherten Datei zu generieren und die archivierte Version in meine Unterklasse einzubetten (xxd -i path/to/file
) .
Innerhalb initWithRootViewController
entarchiviere ich diese Vorlage und setze mich auf das Ergebnis des Unarchivs:
// 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];
}
Dann kann ich einfach eine neue Instanz meiner UIViewController-Unterklasse abrufen, für die die benutzerdefinierte Navigationsleiste festgelegt ist:
UIViewController *modalViewController = [[[CTNavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[self.navigationController presentModalViewController:modalViewController animated:YES];
Dies gibt mir einen modalen UITableViewController mit einer Navigationsleiste und einer Symbolleiste, die alle eingerichtet sind, und mit der benutzerdefinierten Navigationsleistenklasse. Ich musste keinen leicht unangenehmen Methodenersatz durchführen, und ich muss mich nicht mit Schreibfedern herumschlagen, wenn ich wirklich nur programmgesteuert arbeiten möchte.
Ich würde gerne das Äquivalent von +layerClass
UINavigationController sehen - +navigationBarClass
- aber im Moment funktioniert dies.