web-dev-qa-db-fra.com

La vue ne se met pas à jour après avoir modifié par programme les contraintes de mise en page automatique

Avant, je dois dire que j'ai effectivement obtenu l'effet visible que je voulais, mais pas de manière satisfaisante car, pour le moment, les contraintes doivent être "brisées" au lieu d'être correctement mises à jour.

J'ai obtenu un ViewController qui contient un UITableView. La hauteur de ce tableView peut varier de 0 (non visible) au nombre de lignes qu'il contient. La hauteur est calculée dans viewDidLoad () de ViewController en multipliant le nombre actuel de lignes par la hauteur de la ligne.

La première chose que j'ai essayée a été de créer un @IBOutlet weak var tableHeightConstraint: NSLayoutConstraint! Connecté à la contrainte de hauteur définie dans le storyboard. Il a juste une hauteur initiale aléatoire mais il est mis à jour à la valeur correcte dans viewDidLoad() de ViewController suivie d'une méthode qui met à jour la vue si nécessaire:

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()

... et même les mêmes méthodes sur tableView juste pour être sûr ainsi que de mettre tout cela dans viewDidLayoutSubviews() à la place.

J'ai donc essayé de créer la même contrainte que ci-dessus, mais au lieu de la mettre à jour, je l'ai simplement ajoutée à la vue: view.addConstraint(tableHeightConstraint). En fait, cela a eu l'effet visuel souhaité, mais dans les journaux, j'ai eu un conflit de ces deux contraintes de hauteur entraînant une rupture de la première. Comme mon objectif est d'obtenir un code correct et propre, j'ai continué à essayer. Cette fois, j'ai donc supprimé la contrainte de la vue avant d'ajouter à nouveau la contrainte ajustée. Visuellement, encore une fois, tout était parfait mais je ne me suis toujours pas débarrassé des contraintes conflictuelles.

Donc, ma vraie question est (en plus de ce que je faisais mal jusqu'à présent) comment je peux - de préférence - simplement mettre à jour une contrainte existante suivie d'une mise à jour/relais appropriée de la vue et de ses sous-vues à tout moment, que ce soit lors du premier chargement une vue ou si je veux juste changer certaines contraintes lorsque l'utilisateur interagit. Merci beaucoup pour toute aide!

17
Alexei S.

Actuellement, vous affectez une nouvelle contrainte, au lieu de mettre à jour la contrainte actuelle. La nouvelle contrainte n'a pas non plus été ajoutée à la hiérarchie des vues.

Votre approche consistant à utiliser un IBOutlet pour référencer une contrainte que vous définissez dans IB est une bonne approche, mais au lieu d'attribuer une nouvelle contrainte à cette variable, il vous suffit de modifier la constante de la contrainte:

tableHeightConstraint.constant = calculatedTableHeight.

Vous ne devriez pas avoir besoin d'appeler layoutIfNeeded () ici, car les contraintes gèrent l'appel d'une disposition passent automatiquement lorsque vous modifiez leurs constantes. updateConstraints() et layoutSubviews() ne sont définitivement pas ce que vous voulez.

30
cmyr