Lorsque mes "lignes" UIStackView sont écrasées, elles lancent AutoLayout
avertissements. Cependant, ils s'affichent bien et rien d'autre n'est faux à part ces types de journalisation:
Impossible de satisfaire simultanément les contraintes. Vous ne voulez probablement pas qu'au moins une des contraintes de la liste suivante. Essayez ceci: (1) regardez chaque contrainte et essayez de comprendre à laquelle vous ne vous attendez pas; (2) trouvez le code qui a ajouté la ou les contraintes indésirables et corrigez-le. (Remarque: si vous constatez
NSAutoresizingMaskLayoutConstraints
que vous ne comprenez pas, reportez-vous à la documentation de laUIView
propriététranslatesAutoresizingMaskIntoConstraints
) (
Donc, je ne sais pas encore comment résoudre ce problème, mais cela ne semble rien casser en plus d'être ennuyeux.
Quelqu'un sait-il comment le résoudre? Fait intéressant, les contraintes de mise en page sont assez souvent étiquetées avec «UISV-Hiding» , indiquant qu'il devrait peut-être ignorer les minimums de hauteur pour les sous-vues ou quelque chose dans ce cas?
la source
Réponses:
Vous rencontrez ce problème car lorsque vous définissez une sous-vue de l'intérieur
UIStackView
sur masquée, elle contraint d'abord sa hauteur à zéro afin de l'animer.J'obtenais l'erreur suivante:
Ce que j'essayais de faire, c'était de placer un
UIView
dans monUIStackView
qui contenait unUISegmentedControl
encart de 8pts sur chaque bord.Lorsque je le définissais sur masqué, il tentait de contraindre la vue du conteneur à une hauteur nulle, mais comme j'ai un ensemble de contraintes de haut en bas, il y avait un conflit.
Pour résoudre le problème, j'ai changé ma priorité de 8 points en haut et en bas des contraintes de 1000 à 999 afin que la
UISV-hiding
contrainte puisse alors avoir la priorité si nécessaire.la source
J'avais un problème similaire qui n'était pas facile à résoudre. Dans mon cas, j'avais une vue de pile intégrée dans une vue de pile. UIStackView interne avait deux étiquettes et un espacement non nul spécifié.
Lorsque vous appelez addArrangedSubview (), il crée automatiquement des contraintes similaires à celles-ci:
Maintenant, lorsque vous essayez de masquer le innerStackView, vous obtenez un avertissement de contraintes ambiguës.
Pour comprendre pourquoi, voyons d'abord pourquoi cela ne se produit pas quand
innerStackView.spacing
est égal à0
. Lorsque vous appelezinnerStackView.hidden = true
, @liamentnichols avait raison ...outerStackView
interceptera comme par magie cet appel et créera une contrainte de masquage UISV de0
hauteur avec la priorité 1000 (obligatoire). Il s'agit probablement de permettre aux éléments de la vue de la pile d'être animés hors de vue au cas où votre code de masquage serait appelé dans un bloc. Malheureusement, il ne semble pas y avoir de moyen d'empêcher l'ajout de cette contrainte. Néanmoins, vous n'obtiendrez pas un avertissement "Impossible de satisfaire simultanément les contraintes" (USSC), car ce qui suit se produit:UIView.animationWithDuration()
Il est clair que ces 4 contraintes peuvent être satisfaites. La vue de la pile transforme simplement tout en un pixel de 0 hauteur.
Revenons maintenant à l'exemple de buggy, si nous définissons le
spacing
sur2
, nous avons maintenant ces contraintes:La vue de la pile ne peut pas être à la fois haute de 0 pixels et son contenu de 2 pixels de haut. Les contraintes ne peuvent pas être satisfaites.
Remarque: vous pouvez voir ce comportement avec un exemple plus simple. Ajoutez simplement un UIView à une vue de pile en tant que sous-vue organisée. Ensuite, définissez une contrainte de hauteur sur cet UIView avec une priorité de 1000. Maintenant, essayez d'appeler hide.
Remarque: pour une raison quelconque, cela ne s'est produit que lorsque ma vue de pile était une sous-vue d'un UICollectionViewCell ou UITableViewCell. Cependant, vous pouvez toujours reproduire ce comportement en dehors d'une cellule en appelant
innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
la prochaine boucle d'exécution après avoir masqué la vue de la pile interne.Remarque: même si vous essayez d'exécuter le code dans un UIView.performWithoutAnimations, la vue de la pile ajoutera toujours une contrainte de hauteur 0 qui provoquera l'avertissement USSC.
Il existe au moins 3 solutions à ce problème:
spacing
par 0. C'est ennuyeux car vous devez inverser le processus (et vous souvenir de l'espacement d'origine) chaque fois que vous affichez à nouveau le contenu.removeFromSuperview
. C'est encore plus ennuyeux car lorsque vous inversez le processus, vous devez vous rappeler où insérer l'élément supprimé. Vous pouvez optimiser en appelant uniquement removeArrangedSubview, puis en vous cachant, mais il reste encore beaucoup de comptabilité à faire.spacing
) dans un UIView. Spécifiez au moins une contrainte comme priorité non requise (999 ou moins). C'est la meilleure solution puisque vous n'avez pas à faire de comptabilité. Dans mon exemple, j'ai créé des contraintes de haut, de début et de fin à 1000 entre la vue de pile et la vue de wrapper, puis j'ai créé une contrainte 999 du bas de la vue de pile vers la vue de wrapper. De cette façon, lorsque la vue de la pile externe crée une contrainte de hauteur nulle, la contrainte 999 est rompue et vous ne voyez pas l'avertissement USSC. (Remarque: Ceci est similaire à la solution de Si le contentView.translatesAutoResizingMaskToConstraints d'une sous-classe UICollectionViewCell doit être défini surfalse
)En résumé, les raisons pour lesquelles vous obtenez ce comportement sont:
Si Apple (1) vous avait autorisé à spécifier la priorité des contraintes (en particulier les espaceurs), ou (2) vous avait autorisé à désactiver la contrainte de masquage automatique d' UISV , ce problème serait facilement résolu.
la source
UIStackView
enfant d'unUIStackView
besoin d'être enveloppé dans unUIView
ou juste celui que vous cherchez à cacher / dévoiler?UIStackView
ont tendance à être cryptiques et difficiles à comprendre.La plupart du temps, cette erreur peut être résolue en abaissant la priorité des contraintes afin d'éliminer les conflits.
la source
Lorsque vous définissez une vue sur masqué, l '
UIStackview
essaiera de l'animer. Si vous voulez cet effet, vous devrez définir la bonne priorité pour les contraintes afin qu'elles ne soient pas en conflit (comme beaucoup l'ont suggéré ci-dessus).Cependant, si vous ne vous souciez pas de l'animation (peut-être que vous la cachez dans ViewDidLoad), vous pouvez simplifier
removeFromSuperview
ce qui aura le même effet mais sans aucun problème avec les contraintes, car celles-ci seront supprimées avec la vue.la source
Sur la base de la réponse de @ Senseful, voici une extension UIStackView pour envelopper une vue de pile dans une vue et appliquer les contraintes qu'il recommande:
Au lieu d'ajouter votre
stackView
, utilisezstackView.wrapped()
.la source
Tout d'abord, comme d'autres l'ont suggéré, assurez-vous que les contraintes que vous pouvez contrôler, c'est-à-dire pas les contraintes inhérentes à UIStackView, sont définies sur la priorité 999 afin qu'elles puissent être remplacées lorsque la vue est masquée.
Si vous rencontrez toujours le problème, le problème est probablement dû à l'espacement dans les StackViews masquées. Ma solution était d'ajouter un UIView comme espaceur et de définir l'espacement UIStackView à zéro. Définissez ensuite les contraintes View.height ou View.width (en fonction d'une pile verticale ou horizontale) sur l'espacement de StackView.
Ajustez ensuite les priorités de respect du contenu et de résistance à la compression du contenu de vos vues nouvellement ajoutées. Vous devrez peut-être également modifier la distribution du StackView parent.
Tout ce qui précède peut être effectué dans Interface Builder. Vous devrez peut-être en outre masquer / afficher certaines des vues nouvellement ajoutées par programme afin de ne pas avoir d'espacement indésirable.
la source
J'ai récemment lutté contre des erreurs de mise en page automatique en masquant un fichier
UIStackView
. Plutôt que de faire un tas de piles de livres et d'emballageUIViews
, j'ai choisi de créer un point de vente pour mesparentStackView
et des points de vente pour les enfants que je veux cacher / afficher.Dans le storyboard, voici à quoi ressemble mon parentStack:
Il a 4 enfants et chacun des enfants a un tas de vues de pile à l'intérieur d'eux. Lorsque vous masquez une vue de pile, si elle contient des éléments d'interface utilisateur qui sont également des vues de pile, vous verrez un flux d'erreurs de disposition automatique. Plutôt que de me cacher, j'ai choisi de les supprimer.
Dans mon exemple,
parentStackViews
contient un tableau des 4 éléments: Top Stack View, StackViewNumber1, Stack View Number 2 et Stop Button. Leurs indices enarrangedSubviews
sont 0, 1, 2 et 3, respectivement. Lorsque je veux en cacher un, je le supprime simplement duparentStackView's
arrangedSubviews
tableau. Comme il n'est pas faible, il reste en mémoire et vous pouvez simplement le remettre à l'index souhaité plus tard. Je ne le réinitialise pas, donc il se bloque jusqu'à ce qu'il soit nécessaire, mais ne gonfle pas la mémoire.Donc, fondamentalement, vous pouvez ...
1) Faites glisser IBOutlets pour votre pile parent et les enfants que vous souhaitez masquer / afficher dans le storyboard.
2) Lorsque vous souhaitez les masquer, supprimez la pile que vous souhaitez masquer du
parentStackView's
arrangedSubviews
tableau.3) Appelez
self.view.layoutIfNeeded()
avecUIView.animateWithDuration
.Notez que les deux derniers stackViews ne le sont pas
weak
. Vous devez les conserver lorsque vous les affichez.Disons que je veux masquer stackViewNumber2:
Puis animez-le:
Si vous souhaitez "afficher" une version
stackViewNumber2
ultérieure, vous pouvez simplement l'insérer dans l'parentStackView
arrangedSubViews
index souhaité et animer la mise à jour.J'ai trouvé que c'était beaucoup plus facile que de faire de la comptabilité sur les contraintes, de jouer avec les priorités, etc.
Si vous souhaitez masquer quelque chose par défaut, vous pouvez simplement le disposer sur le storyboard, le supprimer
viewDidLoad
et le mettre à jour sans utiliser l'animationview.layoutIfNeeded()
.la source
J'ai rencontré les mêmes erreurs avec les vues de pile intégrées, même si tout fonctionnait bien au moment de l'exécution.
J'ai résolu les erreurs de contrainte en masquant d'abord toutes les vues de la sous-pile (paramètre
isHidden = true
) avant de masquer la vue de la pile parente.Faire cela n'a pas eu toute la complexité de la suppression des vues subordonnées, le maintien d'un index pour le moment où il fallait les rajouter.
J'espère que cela t'aides.
la source
Senseful a fourni une excellente réponse à la racine du problème ci-dessus, je vais donc aller directement à la solution.
Tout ce que vous avez à faire est de définir la priorité de toutes les contraintes stackView à une valeur inférieure à 1000 (999 feront le travail). Par exemple, si le stackView est contraint à gauche, à droite, en haut et en bas de sa vue de supervision, les 4 contraintes doivent avoir la priorité inférieure à 1000.
la source
Vous avez peut-être créé une contrainte en travaillant avec une certaine classe de taille (ex: wCompact hRegular), puis vous avez créé un doublon lorsque vous êtes passé à une autre classe de taille (ex: wAny hAny). vérifiez les contraintes des objets UI dans différentes classes de taille et voyez s'il y a des anomalies avec les contraintes. vous devriez voir les lignes rouges indiquant les contraintes de collision. Je ne peux pas mettre de photo avant d'avoir 10 points de réputation désolé: /
la source
Je voulais cacher tout UIStackView à la fois mais j'obtenais les mêmes erreurs que l'OP, cela a résolu le problème pour moi:
la source
priority = 1000
) en non requise (priority <= 999
).J'avais une rangée de boutons avec une contrainte de hauteur. Cela se produit lorsqu'un bouton est masqué. La définition de la priorité de la contrainte de hauteur des boutons sur 999 a résolu le problème.
la source
Cette erreur n'a rien à voir avec UIStackView. Cela se produit lorsque vous avez des contraintes de conflit avec les mêmes priorités. Par exemple, si vous avez une contrainte indique que la largeur de votre vue est de 100, et que vous avez une autre contrainte en même temps, indique que la largeur de la vue est de 25% de son conteneur. Il y a manifestement deux contraintes contradictoires. La solution est de supprimer l'un d'entre eux.
la source
NOP avec [mySubView removeFromSuperview]. J'espère que cela pourrait aider quelqu'un :)
la source