Wenn meine "Zeilen" von UIStackView gequetscht werden, werden AutoLayout
Warnungen ausgegeben . Sie werden jedoch gut angezeigt und nichts anderes ist falsch als diese Art von Protokollierung:
Einschränkungen können nicht gleichzeitig erfüllt werden. Wahrscheinlich ist mindestens eine der Einschränkungen in der folgenden Liste eine, die Sie nicht möchten. Versuchen Sie Folgendes: (1) Sehen Sie sich jede Einschränkung an und versuchen Sie herauszufinden, welche Sie nicht erwarten. (2) Finden Sie den Code, der die unerwünschte Einschränkung oder die unerwünschten Einschränkungen hinzugefügt hat, und beheben Sie ihn. (Hinweis: Wenn Sie feststellen,
NSAutoresizingMaskLayoutConstraints
dass Sie nicht verstehen, lesen Sie die Dokumentation zurUIView
Eigenschaft.translatesAutoresizingMaskIntoConstraints
) (
Ich bin mir noch nicht sicher, wie ich das beheben soll, aber es scheint nichts zu zerstören, außer nur nervig zu sein.
Weiß jemand, wie man es löst? Interessanterweise werden die Layouteinschränkungen häufig mit "UISV-Ausblenden" gekennzeichnet , was darauf hinweist, dass möglicherweise die Mindesthöhen für Unteransichten oder etwas in diesem Fall ignoriert werden sollten.
quelle
Antworten:
Dieses Problem tritt auf, weil beim Festlegen einer Unteransicht von innen
UIStackView
nach ausgeblendet zunächst die Höhe auf Null beschränkt wird, um sie zu animieren.Ich habe den folgenden Fehler erhalten:
Was ich versuchte zu tun, war ein
UIView
in mein zu platzierenUIStackView
, das einenUISegmentedControl
Einschub von 8 Punkten an jeder Kante enthielt .Wenn ich es auf versteckt setzte, versuchte es, die Containeransicht auf eine Höhe von Null zu beschränken, aber da ich eine Reihe von Einschränkungen von oben nach unten habe, gab es einen Konflikt.
Um das Problem zu beheben, habe ich meine Priorität für 8pt oben und unten von 1000 auf 999 geändert, damit die
UISV-hiding
Einschränkung bei Bedarf Priorität haben kann.quelle
Ich hatte ein ähnliches Problem, das nicht einfach zu lösen war. In meinem Fall war eine Stapelansicht in eine Stapelansicht eingebettet. In der internen UIStackView wurden zwei Beschriftungen und ein Abstand ungleich Null angegeben.
Wenn Sie addArrangedSubview () aufrufen, werden automatisch Einschränkungen erstellt, die den folgenden ähneln:
Wenn Sie nun versuchen, die innerStackView auszublenden, wird eine mehrdeutige Einschränkungswarnung angezeigt.
Um zu verstehen, warum, lassen Sie uns zuerst sehen, warum dies nicht passiert, wenn
innerStackView.spacing
es gleich ist0
. Wenn Sie anrufeninnerStackView.hidden = true
, @liamnichols richtig war ... dasouterStackView
wird diesen Aufruf auf magische Weise abfangen, und schafft0
Höhe UISV-Versteck constrain mit Priorität 1000 (erforderlich). Vermutlich soll dies ermöglichen, dass Elemente in der Stapelansicht außerhalb der Ansicht animiert werden, falls Ihr Versteckcode innerhalb einesUIView.animationWithDuration()
Blocks aufgerufen wird . Leider scheint es keine Möglichkeit zu geben, das Hinzufügen dieser Einschränkung zu verhindern. Sie erhalten jedoch keine Warnung "USSC)" Nicht gleichzeitig erfüllt werden können ", da Folgendes passiert:Es ist klar zu sehen, dass diese 4 Bedingungen erfüllt werden können. Die Stapelansicht glättet einfach alles in ein Pixel mit einer Höhe von 0.
Zurück zum Buggy-Beispiel: Wenn wir den Wert
spacing
auf setzen2
, gelten folgende Einschränkungen:Die Stapelansicht kann nicht beide 0 Pixel hoch sein und ihr Inhalt darf 2 Pixel hoch sein. Die Einschränkungen können nicht erfüllt werden.
Hinweis: Sie können dieses Verhalten anhand eines einfacheren Beispiels sehen. Fügen Sie einer Stapelansicht einfach eine UIView als angeordnete Unteransicht hinzu. Legen Sie dann eine Höhenbeschränkung für dieses UIView mit der Priorität 1000 fest. Versuchen Sie nun, hide aufzurufen.
Hinweis: Aus irgendeinem Grund geschah dies nur, wenn meine Stapelansicht eine Unteransicht einer UICollectionViewCell oder UITableViewCell war. Sie können dieses Verhalten jedoch auch außerhalb einer Zelle reproduzieren, indem Sie
innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
die nächste Ausführungsschleife aufrufen, nachdem Sie die innere Stapelansicht ausgeblendet haben.Hinweis: Auch wenn Sie versuchen, den Code in einer UIView.performWithoutAnimations auszuführen, fügt die Stapelansicht eine Höhenbeschränkung von 0 hinzu, die die USSC-Warnung auslöst.
Es gibt mindestens 3 Lösungen für dieses Problem:
spacing
in diesem Fall den Wert auf 0. Dies ist ärgerlich, da Sie den Vorgang umkehren müssen (und den ursprünglichen Abstand berücksichtigen müssen), wenn Sie den Inhalt erneut anzeigen .removeFromSuperview
. Dies ist umso ärgerlicher, als Sie sich beim Umkehren des Vorgangs merken müssen, wo das entfernte Element eingefügt werden soll. Sie können optimieren, indem Sie nur removeArrangedSubview aufrufen und dann ausblenden. Es ist jedoch noch viel Buchhaltung erforderlich.spacing
Stapelansichten (die nicht Null sind ) in eine UIView einschließen. Geben Sie mindestens eine Einschränkung als nicht erforderliche Priorität an (999 oder niedriger). Dies ist die beste Lösung, da Sie keine Buchhaltung durchführen müssen. In meinem Beispiel habe ich bei 1000 zwischen der Stapelansicht und der Wrapper-Ansicht obere, führende und nachfolgende Einschränkungen erstellt und dann eine 999-Einschränkung vom unteren Rand der Stapelansicht zur Wrapper-Ansicht erstellt. Auf diese Weise wird die 999-Einschränkung unterbrochen, wenn die äußere Stapelansicht eine Einschränkung für die Höhe Null erstellt, und die USSC-Warnung wird nicht angezeigt. (Hinweis: Dies ähnelt der Lösung für Sollte die contentView.translatesAutoResizingMaskToConstraints einer UICollectionViewCell-Unterklasse auf gesetzt seinfalse
)Zusammenfassend sind die Gründe für dieses Verhalten:
Hätte Apple entweder (1) die Angabe der Priorität von Einschränkungen (insbesondere von Abstandshaltern) oder (2) die Deaktivierung der automatischen Einschränkung zum Ausblenden von UISV zugelassen , wäre dieses Problem leicht zu lösen.
quelle
UIStackView
Kind einesUIStackView
Menschen in einUIView
oder nur das eingewickelt werden, das Sie verstecken / einblenden möchten?UIStackView
kryptisch und schwer zu verstehen sind.In den meisten Fällen kann dieser Fehler durch Verringern der Einschränkungspriorität behoben werden, um Konflikte zu beseitigen.
quelle
Wenn Sie eine Ansicht auf "Ausgeblendet" setzen,
UIStackview
wird versucht, sie zu animieren. Wenn Sie diesen Effekt erzielen möchten, müssen Sie die richtige Priorität für die Einschränkungen festlegen, damit sie nicht in Konflikt geraten (wie viele oben vorgeschlagen haben).Wenn Sie sich jedoch nicht für die Animation interessieren (vielleicht verstecken Sie sie in ViewDidLoad), können Sie einfach festlegen,
removeFromSuperview
was den gleichen Effekt hat, jedoch ohne Probleme mit Einschränkungen, da diese zusammen mit der Ansicht entfernt werden.quelle
Basierend auf der Antwort von @ Senseful gibt es hier eine UIStackView-Erweiterung, mit der eine Stapelansicht in eine Ansicht eingeschlossen und die von ihm empfohlenen Einschränkungen angewendet werden können:
Anstatt Ihre hinzuzufügen
stackView
, verwenden SiestackView.wrapped()
.quelle
Stellen Sie zunächst, wie andere vorgeschlagen haben, sicher, dass die Einschränkungen, die Sie steuern können, dh nicht die Einschränkungen, die UIStackView inhärent sind, auf Priorität 999 festgelegt sind, damit sie überschrieben werden können, wenn die Ansicht ausgeblendet ist.
Wenn das Problem weiterhin auftritt, liegt das Problem wahrscheinlich an den Abständen in den ausgeblendeten StackViews. Meine Lösung bestand darin, ein UIView als Abstandshalter hinzuzufügen und den UIStackView-Abstand auf Null zu setzen. Stellen Sie dann die Einschränkungen für View.height oder View.width (abhängig von einem vertikalen oder horizontalen Stapel) auf den Abstand der StackView ein.
Passen Sie dann die Prioritäten für Inhaltsumarmung und Inhaltskomprimierungsbeständigkeit Ihrer neu hinzugefügten Ansichten an. Möglicherweise müssen Sie auch die Verteilung der übergeordneten StackView ändern.
All dies kann in Interface Builder durchgeführt werden. Möglicherweise müssen Sie zusätzlich einige der neu hinzugefügten Ansichten programmgesteuert ein- oder ausblenden, damit Sie keine unerwünschten Abstände haben.
quelle
Ich habe kürzlich mit automatischen Layoutfehlern gerungen, als ich a versteckte
UIStackView
. Anstatt ein paar Bücher zu führen und Stapel einzupackenUIViews
, habe ich mich dafür entschieden, eine Steckdose für meineparentStackView
und Steckdosen für die Kinder zu schaffen, die ich verstecken / einblenden möchte.Im Storyboard sieht mein parentStack folgendermaßen aus:
Es hat 4 Kinder und jedes der Kinder hat eine Reihe von Stapelansichten in sich. Wenn Sie eine Stapelansicht ausblenden und UI-Elemente enthalten, die ebenfalls Stapelansichten sind, wird ein Strom von Fehlern beim automatischen Layout angezeigt. Anstatt mich zu verstecken, entschied ich mich, sie zu entfernen.
In meinem Beispiel
parentStackViews
enthält es ein Array der 4 Elemente: Top Stack View, StackViewNumber1, Stack View Number 2 und Stop Button. Ihre Indizes inarrangedSubviews
sind 0, 1, 2 bzw. 3. Wenn ich eine ausblenden möchte, entferne ich sie einfach aus demparentStackView's
arrangedSubviews
Array. Da es nicht schwach ist, bleibt es im Speicher und Sie können es später einfach wieder auf den gewünschten Index setzen. Ich initialisiere es nicht neu, so dass es nur so lange hängt, bis es benötigt wird, aber das Gedächtnis nicht aufbläht.Im Grunde können Sie ...
1) Ziehen Sie IBOutlets für Ihren übergeordneten Stapel und die untergeordneten Elemente, die Sie ein- oder ausblenden möchten, in das Storyboard.
2) Wenn Sie sie ausblenden möchten, entfernen Sie den Stapel, den Sie aus dem
parentStackView's
arrangedSubviews
Array ausblenden möchten .3) Rufen Sie
self.view.layoutIfNeeded()
mit anUIView.animateWithDuration
.Beachten Sie, dass die letzten beiden StackViews dies nicht sind
weak
. Sie müssen sie aufbewahren, wenn Sie sie einblenden.Angenommen, ich möchte stackViewNumber2 ausblenden:
Dann animiere es:
Wenn Sie ein
stackViewNumber2
späteres "einblenden" möchten , können Sie es einfach in den gewünschtenparentStackView
arrangedSubViews
Index einfügen und das Update animieren.Ich fand das viel einfacher als die Buchhaltung von Einschränkungen, das Herumspielen mit Prioritäten usw.
Wenn Sie etwas haben, das Sie standardmäßig ausblenden möchten, können Sie es einfach im Storyboard auslegen und entfernen
viewDidLoad
und aktualisieren, ohne dass die Animation verwendet wirdview.layoutIfNeeded()
.quelle
Bei eingebetteten Stapelansichten traten dieselben Fehler auf, obwohl zur Laufzeit alles einwandfrei funktionierte.
Ich habe die Einschränkungsfehler behoben, indem ich zuerst alle Unterstapelansichten ausgeblendet habe (Einstellung
isHidden = true
), bevor ich die übergeordnete Stapelansicht ausgeblendet habe.Dies hatte nicht die Komplexität, untergeordnete Ansichten zu entfernen und einen Index zu verwalten, wenn sie wieder hinzugefügt werden mussten.
Hoffe das hilft.
quelle
Senseful hat eine hervorragende Antwort auf die Wurzel des obigen Problems gegeben, sodass ich direkt zur Lösung komme.
Alles, was Sie tun müssen, ist, die Priorität aller StackView-Einschränkungen auf weniger als 1000 zu setzen (999 erledigt die Arbeit). Wenn die Stapelansicht beispielsweise links, rechts, oben und unten auf ihre Übersicht beschränkt ist, sollten alle 4 Einschränkungen eine Priorität von weniger als 1000 haben.
quelle
Möglicherweise haben Sie beim Arbeiten mit einer bestimmten Größenklasse (z. B. wCompact hRegular) eine Einschränkung erstellt und dann beim Wechsel zu einer anderen Größenklasse (z. B. wAny hAny) ein Duplikat erstellt. Überprüfen Sie die Einschränkungen der UI-Objekte in verschiedenen Größenklassen und prüfen Sie, ob Anomalien mit den Einschränkungen vorliegen. Sie sollten die roten Linien sehen, die auf kollidierende Einschränkungen hinweisen. Ich kann kein Bild einfügen, bis ich 10 Reputationspunkte bekomme. Entschuldigung: /
quelle
Ich wollte ganze UIStackViews gleichzeitig ausblenden, bekam aber die gleichen Fehler wie das OP. Dies hat das Problem für mich behoben:
quelle
priority = 1000
) in nicht erforderlich (priority <= 999
) ändern .Ich hatte eine Reihe von Knöpfen mit Höhenbeschränkung. Dies geschieht, wenn eine Schaltfläche ausgeblendet ist. Durch Festlegen der Priorität der Höhenbeschränkung dieser Schaltflächen auf 999 wurde das Problem behoben.
quelle
Dieser Fehler hat nichts mit UIStackView zu tun. Dies passiert, wenn Sie Konfliktbeschränkungen mit denselben Prioritäten haben. Wenn Sie beispielsweise eine Einschränkung haben, die besagt, dass die Breite Ihrer Ansicht 100 beträgt, und eine andere Einschränkung gleichzeitig angibt, dass die Breite der Ansicht 25% des Containers beträgt. Offensichtlich gibt es zwei widersprüchliche Einschränkungen. Die Lösung besteht darin, einen von ihnen zu löschen.
quelle
NOP mit [mySubView removeFromSuperview]. Ich hoffe es könnte jemandem helfen :)
quelle