Es scheint, dass mit viewDidLoad
aktiviertem Xcode 8 alle Viewcontroller-Unteransichten dieselbe Größe von 1000 x 1000 haben. Seltsame Sache, aber okay, war viewDidLoad
noch nie der bessere Ort, um die Ansichten richtig zu dimensionieren.
Aber viewDidLayoutSubviews
ist!
Bei meinem aktuellen Projekt versuche ich, die Größe einer Schaltfläche zu drucken:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"%@", self.myButton);
}
Das Protokoll zeigt eine Größe von (1000x1000) für myButton! Wenn ich mich dann zum Beispiel mit einer Schaltfläche anmelde, zeigt das Protokoll eine normale Größe an.
Ich benutze Autolayout.
Ist es ein Fehler?
ios
autolayout
ios10
xcode8
Martin
quelle
quelle
(0, 0, 1000, 1000)
gebundene Initialisierung ist die neue Art und Weise, wie Xcode Ansichten von IB instanziiert. Vor Xcode8 wurden Ansichten mit ihrer konfigurierten Größe in der XIB erstellt und anschließend direkt nach dem Bildschirm in der Größe geändert. Jetzt ist im IB-Dokument jedoch keine Größe konfiguriert, da die Größe von Ihrer Geräteauswahl abhängt (am unteren Bildschirmrand). Die eigentliche Frage lautet also: Gibt es einen zuverlässigen Ort, an dem die endgültige Größe der Ansichten überprüft werden kann?Antworten:
Mit Interface Builder kann der Benutzer jetzt die Größe aller View Controller im Storyboard dynamisch ändern, um die Größe eines bestimmten Geräts zu simulieren.
Vor dieser Funktion sollte der Benutzer jede Größe des Ansichtscontrollers manuell festlegen. Daher wurde der Ansichts-Controller mit einer bestimmten Größe gespeichert, mit
initWithCoder
der der anfängliche Frame festgelegt wurde.Nun scheint es, dass
initWithCoder
Sie nicht die im Storyboard definierte Größe verwenden und eine Größe von 1000 x 1000 Pixel für die Viewcontroller-Ansicht und alle ihre Unteransichten definieren.Dies ist kein Problem, da Ansichten immer eine der folgenden Layoutlösungen verwenden sollten:
Autolayout und alle Einschränkungen ordnen Ihre Ansichten korrekt an
autoresizingMask, mit der jede Ansicht, an die keine Einschränkung gebunden ist, mit einem Layout versehen wird ( beachten Sie, dass die Einschränkungen für Autolayout und Rand jetzt in derselben Ansicht kompatibel sind \ o /! ).
Aber das ist ein Problem für alle Sachen Layout der Ansicht Schicht bezogen, wie
cornerRadius
, da weder automatisches Layout noch die automatische Maske auf Schichteigenschaften gilt.Um dieses Problem zu lösen, verwenden
viewDidLayoutSubviews
Sie üblicherweise, wenn Sie sich in der Steuerung befinden oderlayoutSubview
wenn Sie sich in einer Ansicht befinden. An diesem Punkt (vergessen Sie nicht, diesuper
relativen Methoden aufzurufen ) sind Sie sich ziemlich sicher, dass alle Layout-Aufgaben erledigt wurden!Ziemlich sicher? Hum ... nicht ganz, habe ich bemerkt, und deshalb habe ich diese Frage gestellt. In einigen Fällen hat die Ansicht bei dieser Methode immer noch die Größe 1000x1000. Ich denke, es gibt keine Antwort auf meine eigene Frage. Um die maximale Information darüber zu geben:
1- es passiert nur beim Auslegen von Zellen! In
UITableViewCell
&UICollectionViewCell
UnterklassenlayoutSubview
wird nicht aufgerufen, nachdem die Unteransichten korrekt angeordnet wurden.2- Wie @EugenDimboiu bemerkte (bitte stimmen Sie seiner Antwort zu, wenn dies für Sie nützlich ist), wird das Aufrufen
[myView layoutIfNeeded]
der nicht angelegten Unteransicht gerade rechtzeitig korrekt angeordnet.3- Meiner Meinung nach ist dies definitiv ein Fehler. Ich habe es beim Radar eingereicht (ID 28562874).
PS: Ich bin kein englischer Muttersprachler, also zögern Sie nicht, meinen Beitrag zu bearbeiten, wenn meine Grammatik korrigiert werden sollte;)
PS2: Wenn Sie eine bessere Lösung haben, schreiben Sie keine weitere Antwort. Ich werde die akzeptierte Antwort verschieben.
quelle
UIStackView
Innenseite von aUICollectionViewCell
währenddessen nicht die richtige Höhe zurückgabviewDidLayoutSubviews
. Durch einenlayoutIfNeeded
sofortigen Anruf wurde das Problem behoben.Verwenden Sie abgerundete Ecken für Ihren Knopf? Versuchen Sie
layoutIfNeeded()
vorher anzurufen .quelle
Lösung: Wrap alles innen
viewDidLayoutSubviews
inDispatchQueue.main.async
.quelle
-viewDidLoad
... eine so seltsameIch weiß, dass dies nicht Ihre genaue Frage war, aber ich bin auf ein ähnliches Problem gestoßen, bei dem einige meiner Ansichten wie beim Update durcheinander gebracht wurden, obwohl in viewDidLayoutSubviews die richtige Frame-Größe vorhanden war. Laut iOS 10 Versionshinweise:
Grundsätzlich können Sie layoutIfNeeded nicht für ein untergeordnetes Objekt der Ansicht aufrufen, wenn Sie translatesAutoresizingMaskIntoConstraints verwenden. Jetzt muss der Aufruf von layoutIfNeeded in der SuperView erfolgen, und Sie können dies weiterhin in viewDidLayoutSubviews aufrufen.
quelle
Wenn die Frames in layoutSubViews nicht korrekt sind (was sie nicht sind), können Sie ein bisschen Code im Hauptthread asynchron versenden. Dies gibt dem System einige Zeit, um das Layout zu erstellen. Wenn der von Ihnen versendete Block ausgeführt wird, haben die Frames die richtige Größe.
quelle
Dies hat das (lächerlich nervige) Problem für mich behoben:
Bearbeiten / Hinweis: Dies ist für einen ViewController im Vollbildmodus.
quelle
[super viewDidLayoutSubviews];
diese Methode aufrufen , da viele Autolayout-Aufgaben von der Ansicht selbst ausgeführt werdenUIView
s korrekt gestalten . Wenn Sie jedoch eine spezielle Berechnung für einen bestimmten Ansichtsrahmen durchführen müssen, funktioniert Eugens Antwort: RufenlayoutIfNeeded
Sie ihn auf. Ich habe das Gefühl, dass dies nicht die beste Lösung ist, aber ich habe immer noch keine bessere gefunden.Eigentlich
viewDidLayoutSubviews
ist auch nicht der beste Ort, um den Rahmen Ihrer Ansicht festzulegen. Soweit ich verstanden habe, sollte von nun an nur noch dielayoutSubviews
Methode im Code der eigentlichen Ansicht durchgeführt werden. Ich wünschte ich hätte nicht recht, jemand korrigiert mich bitte wenn es nicht wahr ist!quelle
viewDidLayoutSubviews
ist ziemlich zweideutig. Der zweite Satz in "Diskussionen" widerspricht in gewisser Weise dem letzten. developer.apple.com/reference/uikit/uiviewcontroller/…Ich habe dieses Problem bereits an Apple gemeldet. Dieses Problem besteht seit langer Zeit, als Sie UIViewController von Xib aus initialisieren, aber ich habe eine gute Lösung gefunden. Darüber hinaus habe ich dieses Problem in einigen Fällen festgestellt, wenn layoutIfNeeded in UICollectionView und UITableView verwendet wurde, wenn die Datenquelle nicht im ersten Moment festgelegt wurde, und es auch benötigt wurde, um es zu ändern.
Versand einmalige Verlängerung:
Swizzle-Erweiterung:
quelle
Mein Problem wurde durch Ändern der Verwendung von gelöst
zu
Also von Did zu Will
Super komisch
quelle
Bessere Lösung für mich.
Verwenden von
quelle
Überschreiben Sie layoutSublayers (von Layer: CALayer) anstelle von layoutSubviews in der Zellenunteransicht, um korrekte Frames zu erhalten
quelle
Wenn Sie etwas basierend auf dem Rahmen Ihrer Ansicht tun müssen, überschreiben Sie layoutSubviews und rufen Sie layoutIfNeeded auf
Ich hatte das Problem, dass viewDidLayoutSubviews den falschen Frame für meine Ansicht zurückgab , für den ich einen Farbverlauf hinzufügen musste. Und nur layoutIfNeeded hat das Richtige getan :)
quelle
Laut neuem Update in ios ist dies tatsächlich ein Fehler, aber wir können dies reduzieren, indem wir -
Wenn Sie xib mit Autolayout in Ihrem Projekt verwenden, müssen Sie nur den Frame in der Autolayout-Einstellung aktualisieren. Bitte finden Sie ein Bild dafür.
quelle