2014-10-22 1 views
16

Vorweg muss ich sagen, dass ich tatsächlich den sichtbaren Effekt, den ich wollte, aber nicht in einer befriedigenden Art und Weise, jetzt, Einschränkungen müssen "gebrochen" statt ordnungsgemäß aktualisiert werden.View wird nicht aktualisiert nach dem Ändern von Auto-Layout-Einschränkungen programmgesteuert

Ich habe einen ViewController, der eine UITableView enthält. Die Höhe dieses tableView kann von 0 (nicht sichtbar) bis zu der Anzahl der Zeilen variieren, die es enthält. Die Höhe wird in ViewDidLoad() des ViewControllers berechnet, indem die aktuelle Anzahl der Zeilen mit der Höhe der Zeile multipliziert wird.

Das erste, was ich ausprobiert habe, war die Erstellung eines @IBOutlet weak var tableHeightConstraint: NSLayoutConstraint!, der mit dem im Storyboard festgelegten Höhenbeschränkung verbunden ist. Es hat nur einige zufällige Anfangshöhe, aber es wird viewDidLoad() durch angewandte Methode in dem Viewcontroller des auf den korrekten Wert aktualisiert, der die Ansicht aktualisiert, wenn nötig:

tableHeightConstraint = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 0, constant: calculatedTableViewHeight) 

// At this point I've tried a variety of methods like the following two but actually none has worked for me 
view.layoutIfNeeded() 

// or 
view.updateConstraints() 

// or 
view.layoutSubviews() 

... und sogar die gleichen Methoden an Tableview, nur um sicher zu sein, sowie setzen alle diese in viewDidLayoutSubviews() stattdessen.

Also was ich als nächstes versucht habe, war die gleiche Einschränkung wie oben zu erstellen, aber anstatt zu aktualisieren, ich habe es gerade in der Ansicht hinzugefügt: view.addConstraint(tableHeightConstraint). Dies hatte tatsächlich den gewünschten visuellen Effekt, aber in den Logs kam es zu einem Konflikt dieser beiden Höhenbeschränkungen, was zu einem Bruch des ursprünglichen Ergebnisses führte. Mein Ziel ist es, einen korrekten und sauberen Code zu erhalten, den ich immer wieder versucht habe. Dieses Mal habe ich zuerst die Einschränkung aus der Ansicht entfernt, bevor ich die angepasste wieder hinzufüge. Optisch war wieder alles perfekt, aber ich konnte die widersprüchlichen Zwänge nicht beseitigen.

Also meine eigentliche Frage ist (abgesehen davon, was ich bis jetzt falsch gemacht habe), wie ich - vorzugsweise - nur eine vorhandene Einschränkung aktualisieren kann, gefolgt von einer korrekten Aktualisierung/Weitergabe der Ansicht und ihrer Unteransichten an jedem Punkt, egal wenn ich zum ersten Mal eine Ansicht lade oder wenn ich nur einige Einschränkungen ändern möchte, wenn der Benutzer interagiert. Vielen Dank für jede Hilfe!

+0

Wenn Sie die Eigenschaft auf eine neue Integritätsbedingung festlegen, wird die alte nicht entfernt. Dadurch wird der Zeiger nur auf eine neue Integritätsregel gesetzt, weshalb Sie in Konflikt stehende Integritätsbedingungen erhalten. Sie sollten es wie in der Antwort von @cmyr tun. – rdelmar

+0

@rdelmar Ok, verstanden, danke für diese Erklärung! Aber warum gab es immer noch einen Konflikt, wenn man nach 'view.removeConstraint (tableHeightConstraint)' suchte, einen neuen erzeugte und ihn erneut zur Ansicht hinzufügte durch 'view.addConstraint (tableHeightConstraint)' '? Nur um Gründe zu verstehen ... –

+1

Was ist View in dieser Aussage? Ist es die Selbstbetrachtung des Controllers? Eine Höhenbeschränkung, die Sie im Storyboard vornehmen, wird zu der Ansicht hinzugefügt, in der Sie die Höhe festlegen, die Tabellenansicht in Ihrem Fall (nicht in der Superansicht). Haben Sie versucht, self.tableView.removeConstraint (tableHeightConstraint)? Der neue sollte auch der Tabellenansicht hinzugefügt werden. – rdelmar

Antwort

29

Derzeit weisen Sie eine neue Einschränkung zu, anstatt die aktuelle zu aktualisieren. Die neue Einschränkung wurde auch nicht zur Ansichtshierarchie hinzugefügt.

Ihr Ansatz eine IBOutlet der Verwendung eine Einschränkung Sie in IB einrichten zu verweisen ist ein guter Ansatz, sondern eine neue Beschränkung auf diese var zuzuweisen, müssen Sie nur die Einschränkung Konstante ändern:

tableHeightConstraint.constant = calculatedTableHeight.

Sie sollten layoutIfNeeded() hier nicht aufrufen müssen, da Constraints das Aufrufen eines Layout-Durchlaufs automatisch übernehmen, wenn Sie ihre Konstanten ändern. updateConstraints() und layoutSubviews() sind definitiv nicht das, was Sie wollen.

+0

Ich würde wirklich gerne in der Lage sein, einfach den Zeiger zu ändern, um auf eine andere Beschränkung zu verweisen, um zwischen zwei Modi eleganter zu wechseln. Es scheint jedoch nicht, dass eine Aktualisierungsnachricht dazu führt, dass die neu referenzierte Einschränkung die vorherige ersetzt. Muss ich jedes Mal, wenn ich den Modus wechseln möchte, die betreffenden Einschränkungen hinzufügen und entfernen? – Michael

+0

@Michael: die Referenz, die Sie an der Einschränkung halten, ist für Ihren eigenen Gebrauch; Wenn Sie einer Ansicht eine Einschränkung hinzufügen und keine Referenz darauf speichern, wird sie immer noch zur Ansicht hinzugefügt. – cmyr

+0

Ja, es macht Sinn; einfacher zu verstehen, wenn Sie an Einschränkungen einer Ansicht denken, einfach als ein Array von Elementen. Eine XIB-Einschränkung, die mit einem IBOutlet verknüpft ist, ist nur eine Möglichkeit, die Abhängigkeit zu initialisieren und sie dem Array beim ersten Laden hinzuzufügen. Das Ändern des Zeigers in Ihrem Controller ändert nichts, was bereits in dem Array ist, während das Ändern einer Eigenschaft der Einschränkung (d. H. Konstant) einen Wert ändert und einen tatsächlichen Effekt hat. – Michael

Verwandte Themen