Wann wird layoutSubviews aufgerufen?
-
05-09-2019 - |
Frage
Ich habe eine benutzerdefinierte Ansicht, die nicht angezeigt wird layoutSubview
Nachrichten während der Animation.
Ich habe eine Ansicht, die den Bildschirm ausfüllt.Es verfügt über eine benutzerdefinierte Unteransicht am unteren Bildschirmrand, deren Größe im Interface Builder korrekt angepasst wird, wenn ich die Höhe der Navigationsleiste ändere. layoutSubviews
wird aufgerufen, wenn die Ansicht erstellt wird, aber nie wieder.Meine Unteransichten sind korrekt angeordnet.Wenn ich die Anrufstatusleiste ausschalte, wird die Unteransicht angezeigt layoutSubviews
wird überhaupt nicht aufgerufen, obwohl die Hauptansicht ihre Größenänderung animiert.
Unter welchen Umständen ist layoutSubviews
eigentlich angerufen?
Ich habe autoresizesSubviews
einstellen NO
für meine benutzerdefinierte Ansicht.Und im Interface Builder habe ich die oberen und unteren Streben und den vertikalen Pfeil festgelegt.
Ein weiterer Teil des Rätsels besteht darin, dass das Fenster zum Schlüssel gemacht werden muss:
[window makeKeyAndVisible];
Andernfalls wird die Größe der Unteransichten nicht automatisch geändert.
Lösung 5
raupen ich die Lösung auf Interface Builder Beharren, die Federn nicht auf eine Ansicht geändert werden, dass die simulierten Bildschirmelemente eingeschaltet (Statusleiste, etc.) hat. Da die Federn für die Hauptansicht waren ausgeschaltet, könnte diese Ansicht nicht Größe ändern und daher wurde in seiner Gesamtheit nach unten gescrollt, wenn die in-Call-Bar erschien.
die simulierten Funktionen ausschalten, dann die Ansicht Ändern der Größe und die Federn Einstellung richtig die Animation verursachte aufzutreten und meine Methode aufgerufen werden.
Ein zusätzliches Problem bei der Fehleranalyse ist, dass der Simulator die App beendet wird, wenn der in-Call-Status über das Menü umgeschaltet wird. Beenden app = kein Debugger.
Andere Tipps
hatte ich eine ähnliche Frage, aber war mit der Antwort nicht zufrieden (oder alle, die ich im Netz finden konnte), so habe ich versucht, es in der Praxis, und hier ist, was ich habe:
-
init
verursacht keinelayoutSubviews
zu werden genannt (duh) -
addSubview:
UrsachenlayoutSubviews
zu auf dem heißen Ansicht hinzugefügt wird, die Ansicht, es wird bis (Zielansicht) hinzugefügt, und das ganze Subviews des Ziels - Ansicht
setFrame
intelligent ruftlayoutSubviews
auf die Ansicht zu haben eingestellt sein Rahmen nur wenn die Größenparameter des Rahmens ist, verschiedene - Scrollen eine UIScrollView
Ursachen
layoutSubviews
auf genannt werden die Scrollview und seine Superview - Drehen einer Vorrichtung nur Anrufe
layoutSubview
auf der Elternansicht (die reagiert Viewcontrollers primären Ansicht) - eine Ansicht Ändern der Größe wird
layoutSubviews
auf seine Superview rufen
Meine Ergebnisse - http: // blog. logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/
Auf der Grundlage der vorherigen Antwort von @BadPirate, experimentierte ich ein bisschen weiter und kam mit einigen Präzisierungen / Korrekturen nach oben. Ich fand, dass layoutSubviews:
wird auf einer Ansicht aufgerufen werden, wenn und nur wenn:
- Die eigenen Grenzen (nicht Rahmen) geändert.
- Die Grenzen eines seiner direkten Subviews geändert.
- ein Subview der Ansicht hinzugefügt oder aus der Ansicht entfernt.
Einige relevante Details:
- Die Grenzen betrachtet werden nur geändert, wenn der neue Wert ist anders, mit einer anderen Herkunft . Beachten Sie speziell ist, warum
layoutSubviews:
, wenn ein UIScrollView scrollt genannt wird, wie es das Scrollen führt durch seine Grenzen Ursprung zu ändern. - Ändern der Rahmen wird nur die Grenzen ändern, wenn die Größe geändert hat, da dies das einzige, was an die Grenzen Eigentum propagiert wird.
- Eine Änderung der Grenzen einer Ansicht, die noch nicht in einer Ansicht Hierarchie wird in einem Aufruf zur Folge
layoutSubviews:
, wenn die Ansicht schließlich zu einer Ansicht Hierarchie hinzugefügt wird . - Und nur der Vollständigkeit halber: diese Trigger nicht direkt rufen layoutSubviews, sondern rufen
setNeedsLayout
, die Sätze / wirft eine Flagge. Jede Iteration der Laufschleife für alle Ansichten in der Ansichtshierarchie , wird dieser Flag geprüft. Für jede Ansicht, in der die Flagge gehisst gefunden wird, wirdlayoutSubviews:
sie aufgefordert hat, und das Flag wird zurückgesetzt. Ansichten weiter oben in der Hierarchie wird zuerst geprüft / aufgerufen werden.
Layout -Änderungen können immer dann auftreten, wenn eines der folgenden Ereignisse in einer Ansicht auftritt:
A.Die Größe des Begrenzungsrechtecks einer Ansicht ändert sich.
B.Es kommt zu einer Änderung der Schnittstellenausrichtung, die normalerweise eine Änderung des Begrenzungsrechtecks der Stammansicht auslöst.
C.Der Satz von Core Animation-Unterebenen, die mit der Ebene der Ansicht verknüpft sind, ändert sich und erfordert ein Layout.
D.Ihre Anwendung erzwingt die Ausführung des Layouts durch Aufrufen vonsetNeedsLayout
oderlayoutIfNeeded
Methode einer Ansicht.
e.Ihre Anwendung erzwingt das Layout durch Aufrufen vonsetNeedsLayout
Methode des zugrunde liegenden Ebenenobjekts der Ansicht.
Einige der Punkte in BadPirate Antwort ist nur teilweise wahr:
-
Für
addSubView
PunktaddSubview
verursacht layoutSubviews auf der Ansicht hinzugefügt aufgerufen werden, die Ansicht, es zu (Zielansicht) hinzugefügt werden wird und alle Subviews des Ziels.Es hängt von der (Zielansicht) Autoresize Maske Ansicht. Wenn es Autoresize Maske auf hat, wird layoutSubview auf jedem
addSubview
aufgerufen werden. Wenn es keine Autoresize Maske dann wird layoutSubview nur aufgerufen werden, wenn die Ansicht der (Ziel View) Bildgröße ändert.Beispiel: Wenn Sie UIView programmatisch erstellt (es hat standardmäßig keine Autoresize Maske), wird LayoutSubview nur aufgerufen werden, wenn UIView Rahmen nicht auf jedem
.addSubview
ändertEs ist durch diese Technik, die die Leistung der Anwendung auch erhöht.
-
Für das Gerät Drehpunkt
Rotierende nur ein Gerät layoutSubview auf der Elternansicht aufruft (die Reaktion Viewcontroller primäre Ansicht)
Dies wahr sein kann nur, wenn Ihr VC in der VC-Hierarchie (root bei
window.rootViewController
), auch dies ist häufigste Fall. In iOS 5, wenn Sie einen VC schaffen, aber es ist nicht in jedem anderen VC hinzugefügt, dann wäre dies VC bekommen nicht, wenn das Gerät drehen bemerkt. Daher würde ihre Ansicht nach nicht durch den Aufruf layoutSubviews bemerkt.
Berufung
[self.view setNeedsLayout];
in Viewcontroller es viewDidLayoutSubviews
Sie haben bei layoutIfNeeded geschaut?
Die Dokumentation Schnipsel ist unten. Ist die Animation Arbeit, wenn Sie diese Methode aufrufen explizit während der Animation?
layoutIfNeeded Ordnet die Subviews, wenn nötig.
- (void)layoutIfNeeded
Diskussion Verwenden Sie diese Methode zu zwingen, das Layout Subviews vor dem Zeichnen.
Verfügbarkeit Erhältlich in iPhone OS 2.0 und höher.
Wenn Sie einen OpenGL-App von SDK 3 bis 4 Migration wurde layoutSubviews nicht mehr genannt. Nach einer Menge von Versuch und Irrtum ich MainWindow.xib schließlich geöffnet, ausgewählt, um das Window-Objekt, in dem Inspektor wählte Fensterattribute Registerkarte (ganz links) und überprüfte „Visible beim Start“. Es scheint, dass in SDK 3 noch einen layoutSubviews Anruf führen, nicht jedoch in 4.
6 Stunden Frustration ein Ende setzen.
Ein ziemlich dunkel, aber potenziell wichtiger Fall, wenn layoutSubviews
nie aufgerufen wird, ist:
import UIKit
class View: UIView {
override class var layerClass: AnyClass { return Layer.self }
class Layer: CALayer {
override func layoutSublayers() {
// if we don't call super.layoutSublayers()...
print(type(of: self), #function)
}
}
override func layoutSubviews() {
// ... this method never gets called by the OS!
print(type(of: self), #function)
}
}
let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))