28 Stimmen

Wo wird die UIView-Größe bestimmt?

Zusammenfassung: Wie sollte die UIViewController die Größe seiner UIView-Instanz beim Initialisieren dieser Ansicht kennen?

Die spezielle Initialisierungsmethode für eine UIView ist die initWithFrame:(CGRect)frame Methode. Damit wird der Rahmen für die neu erstellte UIView festgelegt. Diese Methode kann von der Methode UIViewController's loadView-Methode, wenn die Ansicht dieses View-Controllers angefordert wird. Die Dokumentation von UIViewController Zustände in Bezug auf Unterklassenbildung und Ansichtsgröße:

Bei der Erstellung der Ansichten Hierarchie, sollten Sie immer die Auto-Sizing-Eigenschaften Ihrer Views einstellen. Wenn ein View Controller auf dem Bildschirm angezeigt wird, wird seine Root-View normalerweise Größe an den verfügbaren Platz angepasst, der je nach der aktuellen aktuellen Ausrichtung des Fensters und der Vorhandensein von anderen Oberflächenelementen wie zum Beispiel der Statusleiste.

Also, die UIViewController Instanz sollten diese Eigenschaften eingestellt werden. So weit so gut, die UIViewController muss bisher nicht wissen, wie groß seine Aussicht ist oder sein wird.

Wenn die Ansicht eines UIViewController angefordert wird und die View-Eigenschaft Null ist, wird die loadView-Methode des View-Controllers aufgerufen. Nun gibt es ein Problem, denn die UIView muss initialisiert werden, aber der View-Controller weiß noch nicht, welche Größe der View haben soll. Wie groß soll der View initialisiert werden? Wo im Code bestimmen Sie die Größe der Ansicht?

Sie könnten die Ansicht mit einem Null-Rect initialisieren ( CGRectZero ) :

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}

Und lassen Sie den Aufrufer den Ansichtsrahmen wie folgt festlegen:

UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);

Dieser fordert den View vom View-Controller (viewController.view) an und lädt somit dessen View mit der Methode loadView. Diese loadView-Methode initialisiert den View mit einer CGRectZero . Dann setzt der Aufrufer seinen Rahmen (view.frame = ...)

Das Problem ist, dass die Frame-Eigenschaft der Ansicht zweimal gesetzt wird, was möglicherweise noch mehr doppelte Arbeit verursacht, wenn Ihre benutzerdefinierte UIView macht einige erweiterte Layout in der setFrame-Methode (Platzierung und Größenänderung von Unteransichten zum Beispiel). Sie könnten dies verhindern, indem Sie eine eigene Initialisierungsmethode für die UIViewController das den Aufrufer bereits nach einem CGRect fragt, das Sie in einem Ivar speichern würden. Zum Zeitpunkt des Aufrufs der loadView-Methode verwenden Sie dieses Ivar, um die Ansicht zu erstellen.

Was ist hier der richtige Weg? Entweder wird der Rahmen der Ansicht zweimal gesetzt (Initialisierung mit CGRectZero und anschließend setzen), oder die Angabe der UIViewController eine neue Initialisierungsmethode mit einem CGRect (und damit eine Rahmeneigenschaft)? Oder übersehe ich etwas und gibt es andere Möglichkeiten?

8voto

Nikolai Ruhe Punkte 80427

Sie haben keine müssen den vorgesehenen Initialisierer verwenden. Verwenden Sie einfach init wie in [[UIView alloc] init] . Der angegebene Initialisierer muss von den Initialisierern der Unterklassen verwendet werden.

Andererseits kann es nicht schaden, den Rahmen zweimal zu setzen. Das Ausführen vieler Aufgaben in setFrame: ist ungewöhnlich. Das Layouten erfolgt normalerweise in layoutSubviews und wird nur einmal durchgeführt.

0voto

Ben G Punkte 3925

Ich bin derzeit versuchen, die gleiche Sache nach subclassing von UIViewController zu erreichen, um eine generische Komponente zu erstellen und kam etwas ganz seltsam zu bemerken:

UIViewController hat eine "loadView"-Methode, die Sie überschreiben können, um (Zitat der Dokumentation) "Hier sollten Unterklassen ihre benutzerdefinierte View-Hierarchie erstellen".

Also, ich meine Ansichtshierarchie erstellen, Compositing meinen Bildschirm mit einer Standard-Frame-Größe (da ich möglicherweise nicht wissen, den Rahmen, den ich Dinge in der Zeit anzeigen sollte loadView aufgerufen wird).

Aber auf welchen Aufruf hin stelle ich dann die Rahmengrößen richtig ein? Aka: zu welchem Zeitpunkt ist sich mein View-Controller der tatsächlichen Größe seiner Ansicht bewusst?

Muss ich einen "setFrame" in meiner ViewController-Unterklasse erstellen, die das Objekt, das den Viewcontroller erstellt, aufrufen sollte? das scheint seltsam.

drvdijk : Haben Sie eine Lösung für Ihr Problem gefunden?

EDIT : Ich habe gerade diesen Hinweis in der UIViewController-Dokumentation gefunden: Hinweis: Sie sollten keine View-Controller verwenden, um Views zu verwalten, die nur einen Teil ihres Fensters ausfüllen, d.h. nur einen Teil des Bereichs, der durch das Rechteck des Anwendungsinhalts definiert ist. Wenn Sie eine Schnittstelle haben wollen, die aus mehreren kleineren Views besteht, betten Sie sie alle in einen einzigen Root-View ein und verwalten Sie diesen View mit Ihrem View-Controller.

Es scheint also, dass die Hauptansicht von UIViewController immer bildschirmfüllend ist. Punkt.

Das stellt ein Problem für mich aber, wie ich versuche, eine benutzerdefinierte UITabBarViewController zu erstellen (um in der Lage, benutzerdefinierte Bilder in der Registerkarte anzeigen, und nicht blauen Farbverlauf): meine tabBarViewController sollte subviewcontrollers in einen Teil des Fensters nur anzeigen...

0voto

Tafkadasoh Punkte 4499

Möglicherweise möchten Sie die Grenzen des verfügbaren Platzes auf dem Bildschirm berechnen (der vom Vorhandensein anderer Ansichten wie Navigationsleiste, Registerkartenleiste und Statusleiste abhängt). Sie können diese Grenzen dann für den Parameter frame in [[UIView alloc] initWithFrame:] in loadView.

Wenn es das ist, was Sie wollen, dann finden Sie vielleicht meine Antwort hier hilfreich: Bestimmen Sie die richtige Größe in loadView

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X