J'ai un UIView qui se place à l'écran via plusieurs contraintes. Certaines des contraintes appartiennent au superview, d'autres appartiennent à d'autres ancêtres (par exemple, peut-être la propriété view d'un UIViewController).
Je veux supprimer toutes ces anciennes contraintes et les placer dans un nouvel emplacement en utilisant de nouvelles contraintes.
Comment puis-je faire cela sans créer un IBOutlet pour chaque contrainte et avoir à se souvenir de la vue qui possède ladite contrainte?
Pour élaborer, l'approche naïve consisterait à créer un tas d'IBOutlets pour chacune des contraintes, et impliquerait ensuite d'appeler du code tel que:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Le problème avec ce code est que même dans le cas le plus simple, j'aurais besoin de créer 2 IBOutlets. Pour les mises en page complexes, cela pourrait facilement atteindre 4 ou 8 IBOutlets requis. De plus, je devrais m'assurer que mon appel pour supprimer la contrainte est appelé sur la vue appropriée. Par exemple, imaginez que cela myViewsLeftConstraint
appartient à viewA
. Si j'appelais accidentellement [self.view removeConstraint:self.myViewsLeftConstraint]
, rien ne se passerait.
Remarque: La méthode contraintesAffectingLayoutForAxis semble prometteuse, mais est destinée à des fins de débogage uniquement.
Mise à jour: La plupart des réponses que je reçois accord avec self.constraints
, self.superview.constraints
ou une variante de ceux -ci . Ces solutions ne fonctionneront pas car ces méthodes ne renvoient que les contraintes appartenant à la vue, pas celles affectant la vue.
Pour clarifier le problème avec ces solutions, considérez cette hiérarchie de vues:
- Grand-père
- Père
- Moi
- Fils
- Fille
- Frère
- Moi
- Oncle
- Père
Imaginez maintenant que nous créons les contraintes suivantes et que nous les attachons toujours à leur ancêtre commun le plus proche:
- C0: Me: même haut que Son (appartenant à moi)
- C1: Moi: largeur = 100 (appartenant à Moi)
- C2: Moi: même taille que Brother (propriété du père)
- C3: Moi: même haut que l'oncle (appartenant à grand-père)
- C4: Moi: même gauche que Grandfather (propriété de Grandfather)
- C5: Frère: même gauche que Père (propriété du Père)
- C6: Oncle: même gauche que Grandfather (propriété de Grandfather)
- C7: Fils: même gauche que fille (appartenant à moi)
Imaginez maintenant que nous voulons supprimer toutes les contraintes affectant Me
. Toute solution appropriée doit supprimer [C0,C1,C2,C3,C4]
et rien d'autre.
Si j'utilise self.constraints
(où le moi est moi), j'obtiendrai [C0,C1,C7]
, puisque ce sont les seules contraintes que je possède. De toute évidence, il ne suffirait pas de le supprimer car il manque [C2,C3,C4]
. En outre, il supprime C7
inutilement.
Si j'utilise self.superview.constraints
(où le moi est moi), j'obtiendrai [C2,C5]
, puisque ce sont les contraintes détenues par Père. De toute évidence, nous ne pouvons pas supprimer tous ces éléments car cela C5
n'a aucun rapport avec Me
.
Si j'utilise grandfather.constraints
, j'obtiendrai [C3,C4,C6]
. Encore une fois, nous ne pouvons pas supprimer tous ces éléments car ils C6
devraient rester intacts.
L'approche par force brute consiste à boucler sur chacun des ancêtres de la vue (y compris lui-même), et à voir si firstItem
ou secondItem
sont la vue elle-même; si tel est le cas, supprimez cette contrainte. Cela conduira à une solution correcte, à un retour [C0,C1,C2,C3,C4]
, et uniquement à ces contraintes.
Cependant, j'espère qu'il existe une solution plus élégante que de devoir parcourir toute la liste des ancêtres.