Supprimer toutes les contraintes affectant une UIView
J'ai une UIView qui est placé sur l'écran par le biais de plusieurs contraintes. Certaines contraintes sont la propriété de la superview, d'autres sont détenues par d'autres ancêtres (par exemple peut-être le point de vue de la propriété d'un UIViewController).
Je veux enlever tous ces vieux contraintes, et de le placer quelque part de nouveau à l'aide de nouvelles contraintes.
Comment puis-je le faire sans la création d'un IBOutlet pour chaque contrainte et d'avoir à se souvenir de la vue qui est propriétaire de ladite contrainte?
À élaborer, l'approche naïve serait de créer un groupe de IBOutlets pour chacune des contraintes, et serait alors impliquer le code appelant, tels que:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Le problème avec ce code, c'est que même dans le cas le plus simple, j'aurais besoin de créer 2 IBOutlets. Pour des mises en page complexes, ce qui pourrait facilement atteindre 4 ou 8 IBOutlets. En outre, j'aurais besoin de m'assurer que mon appel pour supprimer la contrainte est appelée sur le bon point de vue. Par exemple, imaginez que myViewsLeftConstraint
est détenue par viewA
. Si je ont été accidentellement appel [self.view removeConstraint:self.myViewsLeftConstraint]
, rien ne se passe.
Remarque: La méthode constraintsAffectingLayoutForAxis semble prometteur, mais est destiné à des fins de débogage seulement.
Mise à jour: Beaucoup des réponses que je reçois de traiter avec self.constraints
, self.superview.constraints
, ou des variantes de ceux-ci. Ces solutions ne fonctionnent pas car ces méthodes ne renvoyer que les contraintes appartenant par la vue, pas ceux affectant la vue.
De clarifier le problème avec ces solutions, envisager de ce point de vue de la hiérarchie:
- Grand-père
- Père
- Moi
- Fils
- Fille
- Frère
- Moi
- Oncle
- Père
Maintenant, imaginez que nous créons les contraintes suivantes, et toujours les attacher à leur plus proche ancêtre commun:
- C0: Moi: même en tant que Fils (détenue par Moi)
- C1: Moi: largeur = 100 (détenue par Moi)
- C2: Moi: même hauteur que le Frère (détenue par le Père)
- C3: Moi: même haut que l'Oncle (détenue par le grand-Père)
- C4: Moi: même en tant que grand-Père (détenue par le grand-Père)
- C5: Frère: même en tant que Père (détenue par le Père)
- C6: Oncle: même en tant que grand-Père (détenue par le grand-Père)
- C7: Fils: même en tant que Fille (détenue par Moi)
Maintenant, imaginez que nous voulons supprimer toutes les contraintes affectant Me
. Une solution devrait supprimer [C0,C1,C2,C3,C4]
et rien d'autre.
Si j'utilise self.constraints
(où l'auto est Moi), je vais obtenir [C0,C1,C7]
, puisque ce sont les seules contraintes détenue par Moi. Évidemment, il ne serait pas suffisant pour supprimer ce depuis qu'il est manquant [C2,C3,C4]
. En outre, c'est enlever C7
inutilement.
Si j'utilise self.superview.constraints
(où l'auto est Moi), je vais obtenir [C2,C5]
, puisque ce sont les contraintes de la propriété par le Père. Évidemment, on ne peut pas supprimer tous ces depuis C5
est complètement étranger à Me
.
Si j'utilise grandfather.constraints
, je vais obtenir [C3,C4,C6]
. Encore une fois, nous ne pouvons pas supprimer tous ces depuis C6
doit rester intacte.
L'approche par force brute est de faire une boucle sur chacune de la vue des ancêtres (y compris lui-même), et de voir si firstItem
ou secondItem
sont la vue elle-même; si oui, supprimer cette contrainte. Cela mènera à une solution correcte, le retour [C0,C1,C2,C3,C4]
, et uniquement à ces contraintes.
Cependant, j'espère qu'il y a une solution plus élégante que d'avoir à boucle à travers l'ensemble de la liste des ancêtres.
- Que diriez-vous de mettre un identifiant à toutes les contraintes que vous souhaitez supprimer ? De cette façon, vous n'avez pas besoin de conserver un débouché pour eux.
Vous devez vous connecter pour publier un commentaire.
Cette approche a fonctionné pour moi:
La suite de l'exécution de votre point de vue, où il était parce qu'il crée d'un redimensionnement automatique des contraintes. Quand je ne fais pas ce que la vue disparaît. En outre, il ne fait pas que supprimer les contraintes de superview mais traversant tout le chemin jusqu'à comme il peut y avoir des contraintes dans ancêtre vues.
Swift 4 Version
C7
. Cependant, il devrait être facile à corriger si vous supprimez[self removeConstraints:self.constraints];
et changementUIView *superview = self.superview;
àUIView *superview = self;
.La seule solution que j'ai trouvé pour l'instant est de supprimer la vue de son superview:
Cela ressemble à cela supprime toutes les contraintes qui entravent sa mise en page et est prêt à être ajouté à un superview et avoir de nouvelles contraintes attachées. Cependant, il aura tort de supprimer tout les sous-vues de la hiérarchie en tant que bien, et de se débarrasser de
[C7]
de manière incorrecte.Vous pouvez supprimer toutes les contraintes dans une vue en faisant ceci:
EDIT: Pour supprimer les contraintes de tous les sous-vues, utilisez l'extension suivante dans Swift:
self.constraints
ne renvoie que les contraintes quiself
possède pas toutes les contraintes qui affectentself
.[C6]
, et à tort de ne pas supprimer[C0,C1,C2]
.Dans Swift:
if c.firstItem === self
au lieu de castingas? UIView
et vérifier l'égalité avec==
Il y a deux façons de le réaliser selon Apple Developer Documentation
1.
NSLayoutConstraint.deactivateConstraints
2.
UIView.removeConstraints
(Déconseillé pour >= iOS 8.0)Conseils
À l'aide de
Storyboard
s ouXIB
s peut être une douleur à la configuration de contraintes comme mentionné sur votre scénario, vous devez créer IBOutlets pour chacun de ceux que vous souhaitez supprimer. Même si, la plupart du tempsInterface Builder
crée plus de problèmes qu'elle n'en résout.Par conséquent, lorsque, ayant très dynamique, le contenu et les différents états de la vue, je dirais:
Simple Code
Références
Détails
Solution
Utilisation
Basées sur des réponses précédentes (swift 4)
Vous pouvez utiliser immediateConstraints lorsque vous ne voulez pas de ramper à l'ensemble de hiérarchies.
- Je utiliser la méthode suivante pour supprimer toutes les contraintes de vue:
.h fichier:
.m fichier:
Vous pouvez également lire ce post sur mon blog pour mieux comprendre comment il fonctionne sous le capot.
Si vous avez besoin d'un contrôle plus granulaire, j'avais fortement conseiller de commutation à Maçonnerie, un cadre puissant classe que vous pourriez utiliser à chaque fois que vous avez besoin pour bien gérer les contraintes de la programmation.
Une solution Swift:
Il est important de passer par tous les parents, car les contraintes entre les deux éléments sont dit, par l'ancêtre commun, donc il suffit de compensation de la superview comme détaillé dans cette réponse n'est pas assez bon, et vous pourriez avoir la mauvaise surprise plus tard.
Avec objectiveC
Vous pouvez utiliser quelque chose comme ceci:
En gros, c'est énumère plus de toutes les contraintes sur le superview de viewA et supprime toutes les contraintes qui sont liées à viewA.
Ensuite, la deuxième partie supprime les contraintes de viewA à l'aide de la matrice de viewA contraintes.
[C7]
et, à tort, de ne pas supprimer[C3,C4]
.(Au 31 juillet 2017)
SWIFT 3
Objective C
C'est la façon la plus simple pour supprimer rapidement toutes les contraintes qui existent sur une UIView. Juste être sûr d'ajouter la UIView de retour avec de nouvelles contraintes ou d'un nouveau cadre par la suite =)
Le plus simple et efficace est de supprimer le point de vue de superView et re ajouter en tant que sous-vue de nouveau.
ceci permet à tous les sous-vue les contraintes sont supprimés automatiquement.
C'est la façon de désactiver toutes les contraintes à partir d'un point de vue spécifique