Weiß jemand, wie ich meine benutzerdefinierte Unterklasse verwenden kann, UINavigationBar
wenn ich UINavigationController
programmgesteuert (ohne IB) instanziiere ?
Ziehen Sie eine UINavigationController
in IB, zeigen Sie mir eine unter Navigationsleiste und verwenden Sie Identity Inspectory. Ich kann den Klassentyp ändern und meine eigene Unterklasse festlegen, UINavigationBar
aber programmgesteuert kann ich nicht, die navigationBar
Eigenschaft von Navigation Controller ist schreibgeschützt ...
Was kann ich tun, um die Navigationsleiste programmgesteuert anzupassen? Ist IB "leistungsfähiger" als "Code"? Ich glaubte, dass alles, was in IB gemacht werden kann, auch programmatisch gemacht werden kann.
Antworten:
Sie müssen sich nicht mit dem XIB herumschlagen, sondern verwenden einfach KVC.
quelle
Seit iOS5 bietet Apple eine Methode, um dies direkt zu tun. Referenz
quelle
Ab iOS 4 können Sie die
UINib
Klasse verwenden, um dieses Problem zu lösen.UINavigationBar
Unterklasse.UINavigationController
als einzelnes Objekt hinzu.UINavigationController
‚sUINavigationBar
zu Ihrer benutzerdefinierten Unterklasse.[navController setViewcontrollers[NSArray arrayWithObject:myRootVC]];
[navController pushViewController:myRootVC];
In Code:
Jetzt haben Sie eine
UINavigationController
mit Ihrem BrauchUINavigationBar
.quelle
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:
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:Dann kann ich einfach eine neue Instanz meiner UIViewController-Unterklasse abrufen, für die die benutzerdefinierte Navigationsleiste festgelegt ist:
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.quelle
Ich benutze "Option 1"
Erstellen Sie eine NIB-Datei, in der nur der UINavigationController enthalten ist. Und setzen Sie die UINavigationBar-Klasse auf meine benutzerdefinierte Klasse.
quelle
Michaels Lösung funktioniert, aber Sie können NSKeyedArchiver und das Dienstprogramm 'xxd' vermeiden. Unterklassifizieren Sie einfach UINavigationController und überschreiben Sie es
initWithRootViewController
, indem Sie Ihre benutzerdefinierte NavigationController-NIB direkt laden:quelle
Update: Die Verwendung
object_SetClass()
funktioniert nicht mehr so, als ob iOS5 GM. Eine alternative Lösung wurde unten hinzugefügt.Verwenden Sie NSKeyedUnarchiver, um die nicht archivierte Klasse für die Navigationsleiste manuell festzulegen.
Hinweis: Diese ursprüngliche Lösung funktioniert nur vor iOS5:
Es gibt eine großartige Lösung, die ich hier gepostet habe : Fügen Sie die Unterklasse navBar direkt in Ihre Ansicht ein
UINavigationController
:quelle
Ein Szenario, bei dem ich festgestellt habe, dass wir eine Unterklasse anstelle einer Kategorie verwenden müssen, ist das Festlegen der Hintergrundfarbe der Navigationsleiste mit dem Musterbild, da in iOS5 das Überschreiben von drawRect mithilfe der Kategorie nicht mehr funktioniert. Wenn Sie ios3.1-5.0 unterstützen möchten, können Sie nur die Navigationsleiste der Unterklasse verwenden.
quelle
Diese Kategoriemethoden sind gefährlich und nicht für Anfänger. Auch die Komplikation mit iOS4 und iOS5 macht dies zu einem Bereich, der für viele Menschen Fehler verursachen kann. Hier ist eine einfache Unterklasse, die ich verwende und die iOS4.0 ~ iOS6.0 unterstützt und sehr einfach ist.
.h
.m
quelle
Es wird nicht empfohlen , die Unterklasse
UINavigationBar
Klasse . Die bevorzugte Methode zum Anpassen der Navigationsleiste besteht darin, die Eigenschaften so festzulegen, dass sie wie gewünscht angezeigt werden, und benutzerdefinierte Ansichten in UIBarButtonItems zusammen mit einem Delegaten zu verwenden, um das gewünschte Verhalten zu erzielen.Was versuchst du zu tun, das Unterklassen benötigt?
Ich glaube auch nicht, dass IB tatsächlich die Navigationsleiste ersetzt. Ich bin mir ziemlich sicher, dass es einfach nicht die Standardanzeige anzeigt und Ihre benutzerdefinierte Navigationsleiste als Unteransicht hat. Wenn Sie UINavigationController.navigationBar aufrufen, erhalten Sie eine Instanz Ihrer Leiste?
quelle
Wenn Sie navBar nur zum Ändern des Hintergrundbilds in eine Unterklasse unterteilen möchten, ist dies in iOS 5 nicht erforderlich. Es wird eine Methode wie diese setBackgroundImage geben
quelle
setBackgroundImage:forBarMetrics:
wie hier beschrieben verwenden: developer.apple.com/library/IOS/#documentation/UIKit/Reference/…Nach dem Kommentar von obb64 habe ich schließlich seinen Trick verwendet
setViewControllers:animated:
, um den Controller als denrootController
für dienavigationController
von der Feder geladenen festzulegen. Hier ist der Code, den ich verwende:quelle