2015-06-21 12 views
24

Ich habe ein Storyboard mit Auto-Layout und Größenklassen. Ziemlich kompliziertes Layout, und leider kann ich nicht genau festlegen, wie das Problem in einem neuen Projekt reproduziert werden soll.
Die fragliche Ansicht wird jedoch am linken und rechten Rand des Bildschirms mit einer Einschränkung mit der Priorität 750 fixiert (dh |-([email protected])-[myView]-([email protected])-|, zusätzlich hat eine größere oder gleiche als Einschränkung mit einer Priorität von 1000 (dh |-(>=0)-[myView]-(>=0)-|). Das ist getan, um die Breite auf einem iPad zu beschränken, so gibt es eine Breitenbeschränkung von width <= 600 @1000, und eine Mitte horizontal in Container Einschränkung Darüber hinaus hat die Ansicht eine Seitenverhältnisbeschränkung von 3: 1 sagte, ziemlich kompliziert.Was ist _UITemporaryLayoutWidth und warum bricht es meine Einschränkungen?

Interface Builder zeigt keine Probleme mit den Einschränkungen.Die Xcode-Layout-Vorschau wird für alle Geräte korrekt dargestellt.

Wenn ich die App ausführen sagt mir iOS, dass es widersprüchliche Einschränkungen hat.

Unable to simultaneously satisfy constraints. 
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fd72853ff80 DMXKit.DipSwitchAssembly:0x7fd72990d0e0.width == 3*DMXKit.DipSwitchAssembly:0x7fd72990d0e0.height>", 
    "<NSLayoutConstraint:0x7fd728574e50 '_UITemporaryLayoutWidth' H:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(400)]>", 
    "<NSLayoutConstraint:0x7fd72856e9c0 V:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(133)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7ffb19798000 DMXKit.DipSwitchAssembly:0x7ffb1979a000.width == 3*DMXKit.DipSwitchAssembly:0x7ffb1979a000.height> 

Dies wird einige Male wiederholt, mit den gleichen (d.h.em gleichen pointer) Einschränkungen. Das ist auch merkwürdig, sieht so aus, als wäre die Einschränkung nicht wirklich gebrochen. Wenn sie ausgeführt wird, sieht die App zu 100% korrekt aus. Wenn ich mir die App im Xcode View Debugger anschaue, ist die Einschränkung mit der Adresse 0x7ffb19798000 immer noch da, also wurde sie nie kaputt gemacht.

Woher kommt die Konstanz? Offensichtlich habe ich es nicht hinzugefügt. Google spuckt nichts Nützliches über aus. Ist jemand auf ein Problem wie dieses gestoßen?

+0

, ich habe viel von diese Warnungen auch im Protokoll. Obwohl, scheint es nicht mein Layout zu brechen. Ich frage mich, woher diese '_UITemporaryLayoutWidth's kommen. – dergab

Antwort

0

Die Wurzel des Problems ist das Seitenverhältnis 3: 1. Wenn ich es zu etwas anderem ändere es funktioniert, verwende ich jetzt 4:1.4, das funktioniert. Ich weiß nicht warum, aber es funktioniert.

Ich weiß nicht viel über die Interna von Auto-Layout, aber ich denke, das Problem ist die Reihenfolge, wie die Layout-Engine die Einschränkungen erfüllen will. Größenklassen können der Grund sein, warum die temporäre Breitenbeschränkung hinzugefügt wird.

Die unerfüllbaren Constraints scheinen kein wirkliches Problem zu sein, da sie scheinbar nur vorübergehend nicht erfüllbar sind. Es sind nur ein paar Zeilen des Protokolls, die jedes Mal angezeigt werden, wenn die Ansicht erstellt wird.

44

Also, ich bin mir nicht sicher, ob dies hilft Ihnen mit Ihrem Problem, da es klingt wie Sie Ihr Layout in IB bauen, aber hier ist ein Problem, das gerade helfen, dass andere google Suche nach "_UITemporaryLayoutWidth ".

Mein Szenario war, dass ich automatische Layouteinschränkungen während der Initialisierung hinzufügte und aus Versehen ein "layoutIfNeeded" auslöste, bevor ich die Ansicht der Ansichtshierarchie hinzufügte (das Layout eines Buttons mit Kanteneinsätzen änderte). Es sieht so aus, als ob das System diese temporären Beschränkungen hinzufügt und (ich nehme an?) Sie entfernt, nachdem die Ansicht der Hierarchie hinzugefügt wurde. Die temporären Einschränkungen setzen 0 Dimensionen (in meinem Fall), die fehlschlagen können, wenn Sie zB bestimmte Constraint-Konstantenwerte in Ihrem Layout setzen (zB 16px zwischen diesen Buttons, aber 0 Platz in dieser Dimension ...)

Aktualisierung: Untersuchung ein wenig mehr und festgestellt, dass die temporäre Einschränkung zu dem Rahmen zu entsprechen scheint, die Sie zum Initialisieren der übergeordneten Ansicht verwenden. In meinem Fall hatte der Rahmen, den ich verwendete, die Größe 0x0, daher wurde die Temperatureinschränkung relativ zur 0x0-Größe ausgewertet und ist daher fehlgeschlagen. Verifiziert, dass, wenn ich mit einem 5x5 Rahmen init, dann sehe ich den gleichen Fehler mit _UITemporaryLayoutWidth (5) Einschränkung.Die andere Sache, die ich bemerkt habe, ist, dass die Einschränkung hinzugefügt und entfernt wird während der Layout-Auswertung - wenn ich direkt vor dem Auslösen des Layouts breche und die Einschränkungen analysiere, dann sehe ich die Temperaturbeschränkungen nicht. Ich sehe auch nicht die Einschränkungen nach dem Fehler, also vermute ich, dass sie die Temperaturbeschränkungen synthetisieren, hinzufügen, lösen und dann entfernen.

Update 2: Ok, vielleicht ist dies TMI, aber das könnte für jemanden von Nutzen sein. Mein aktueller Gedanke ist, dass diese temporären Beschränkungen einen Einblick geben, wie das System gemischte Frame-Manipulationen und das automatische Layout innerhalb einer einzelnen View-Hierarchie handhabt. In meinem Fall hatte meine Ansicht keine Eltern und hatte keine Beschränkungen, die ihre Größe definieren, aber sie hatte einen Nullrahmen, was bedeutete, dass das System angenommen hat, dass es die Größe ist, die es verwenden sollte, um das Layout zu lösen. Mein Gedanke ist, dass das System diese Temperaturbeschränkungen für Ansichten synthetisiert, deren Frames explizit gesetzt wurden, um den Rest des Systems zu lösen, während es die Hierarchie durchläuft.

Update 3: Also, ich lief wieder in dieses Problem und wollte ein wenig mehr Informationen teilen. Mein Szenario war, dass ich im Wesentlichen Ansichten zu messen versuchte, die kein Elternteil mit der SystemLayoutSizeFittingSize: -Methode hatten. Lange Rede, kurzer Sinn, ich musste layoutIfNeeded in der Ansicht aufrufen, bevor ich es vermessen habe - da stoße ich auf den Konflikt mit den Temp-Constraints, da die View keine Superview hat. Die Temp-Constraint-Konstanten (die Dimensionen) entsprechen dem Frame, der in der View ohne Superview gesetzt wird - ich denke, das ist sinnvoll (obwohl das Setzen eines Frames in einer View, die Sie mit AutoLayout verwenden, seltsam erscheint. .) Ich konnte das Problem mit der Temperaturbeschränkung umgehen, indem ich sagte: Wenn die Ansicht keine Superview hat, dann füge sie zu einer temporären Superview hinzu; messen; entferne es aus der temporären Superview. Ich hoffe, das ist nützlich.

+12

... "Auslösen eines 'layoutIfNeeded' vor dem Hinzufügen der Ansicht zur Ansichtshierarchie" - Danke dafür. – Adama

+0

Reisende, die Antwort, die Sie suchen, wird von Adama in dem obigen Kommentar zusammengefasst. – Jano

+0

Ist mir passiert, wenn eine Ansicht noch keine Superview hatte, aber die Subviews würden mit AutoLayout ein komplexes Layout haben. – DevAndArtist

6

ich meinem Fall war das Problem folgendes:

ich eine UIButton erstellt.
Ich setze seine Breiten- und Höhenbeschränkungen.
Ich habe die Schaltfläche zu seinem Superview hinzugefügt.
Ich lege seine führenden und Top-Layout-Einschränkungen auf die Superview.

Dies verursachte den Fehler "Unable to simultaneously satisfy constraints" und eine der widersprüchlichen Einschränkungen war _UITemporaryLayoutHeight.

Als ich die Schaltfläche zu seinem Superview vor setzte seine Breite und Höhe Einschränkungen, war der Fehler weg.

6

Wie oben erwähnt, scheinen die temporären Einschränkungen für Ansichten festgelegt zu sein, die keine übergeordnete Ansicht haben. Ich habe festgestellt, dass translatesAutoresizingMaskIntoConstraintsfalse in der Top-Level-Ansicht sicherzustellen, die vorübergehenden Einschränkungen entfernt. As:

topView.translatesAutoresizingMaskIntoConstraints = false 
0

Nur eine schnelle Zusätzlich zu den obigen Ausführungen, die einfache Lösung, die für mich gearbeitet wurde die Reihenfolge zu ändern, in dem sich meine Zwänge geschaffen. Ich habe programmgesteuert Beschränkungen für Ansichten und Superviews erstellt, aber ich machte die Ansichten vor den Superviews. Also habe ich es umgetauscht, so dass die Superview-Einschränkungen zuerst gingen, dann wurden die Abhängigkeiten der Subviews hinzugefügt, und das bedeutete, dass es keinen Aufruf mehr für die _UITemporaryLayoutWidth gab, und so verschwanden die Constraint-Probleme.

0

In meiner Situation, ich habe nur diese UITemporaryLayoutWidth Konflikt in dieser Situation 1 mache ich eigentlich eine Ansicht mit [UIView neu], und ich habe es nicht zu einer Überblicks hinzufügen 2 dann eine Breite Einschränkung i gerade dieser Ansicht erstellen erstellt werden 3 invoke layoutIfNeeded sofort zu dieser Ansicht, und der Konflikt geschieht

so die Möglichkeit, diesen Fehler zu beseitigen, ist einfach: rufen sie nicht layoutIfNeeded, um es selbst vor zu einem gewissen Super

hinzugefügt
Verwandte Themen