Background Image
TECHNOLOGIE

Comment déboguer NSLayout- Constraints (LayoutBeast)

Julian Builes

Consultant principal
Asset - Julian Builes Photo for profile

January 18, 2023 | 7 Lecture minute

Lors de l'écriture d'applications iOS, peu de choses sont plus frustrantes (et plus courantes) que les conflits AutoLayout. Vous prenez le temps de visualiser votre belle mise en page, de créer une image mentale de la hiérarchie des vues, et peut-être même d'esquisser un joli dessin...

Asset - How To Debug NSLayoutConstraints (LayoutBeast) blog photo 1

Mais une fois que vous avez compilé et exécuté votre application, BOOM ! elle vous explose à la figure et les choses ne se présentent pas comme prévu. Vous vous grattez la tête et tout ce qu'il vous reste à faire, c'est de lire des logs de mise en page cryptiques qui peuvent être intimidants et effrayants à lire. Cela vous semble familier ? Ne vous inquiétez pas, je suis là pour vous aider.

Je peux vous promettre qu'après avoir passé quelques minutes à lire cet article, vous verrez que les choses ne sont pas si terribles après tout : vous survivrez, la vie continuera, et vous serez capable de déboguer les conflits de mise en page comme un pro en un rien de temps. Ok, maintenant que nous avons fait le tour de la question, entrons dans le vif du sujet !

Types d'erreurs de mise en page

Insatisfaisant

Il y a des informations contradictoires/confuses dans votre logique de mise en page.

  • Ex : Une contrainte dit "faire une largeur de 400", mais une autre contrainte dit "en fait, faire une largeur de 325".

Ambiguë

Il n'y a pas assez d'informations sur la mise en page pour résoudre les contraintes.

  • Ex : Votre logique dit "faire une largeur de 200, coordonnée x 0, coordonnée y 25" mais vous avez oublié de spécifier la hauteur.

Logique

Il y a un bug dans votre mise en page.

  • Ex : faire en sorte que la vue soit 35 points plus grande que la vue parent, mais vous avez oublié de spécifier quelle est la vue parent.

Contrôles d'intégrité

Vérifiez mentalement ces cases avant de commencer à déboguer :

1. Toute la logique de mise en page s'est-elle exécutée correctement ?

  • La disposition d'une vue peut dépendre d'une dimension spécifique calculée, ou d'une vue existante à configurer correctement.

  • Certaines dispositions peuvent devoir être spécifiées dans un certain ordre. Si c'est le cas, assurez-vous d'en être conscient et veillez à ce que l'ordre des événements soit correct. L'ajout de sous-vues à une vue en pile en est un bon exemple.

2. Avez-vous défini l'option translatesAutoresizingMaskIntoConstraints à false lors de l'ajout de contraintes par programme ?

  • Le constructeur d'interface définira automatiquement cette valeur si vous ajoutez des contraintes sur le canevas, mais cela ne se produira pas lorsque vous ajoutez des contraintes par programme.

  • ASTUCE : Vous verrez NSAutoresizingMaskLayoutConstraint dans l'une de vos contraintes conflictuelles dans les journaux.

3. La hiérarchie de la vue est-elle complète ?

  • Assurez-vous que vous avez instancié les vues parentales et que les vues enfants sont ajoutées au parent en tant que sous-vues de manière appropriée.

4. Ajoutez-vous des contraintes à la fois par programme et dans les Storyboards ?

  • J'essaie d'éviter cela autant que possible. Les storyboards ont tendance à faire des choses magiques dont je ne suis parfois pas conscient, tandis que les programmes sont responsables de chaque étape. Cela rend les choses un peu plus difficiles à déboguer.

Lecture des journaux de conflits de contraintes

AutoLayout to plain dummy Traducteur anglais

Les contraintes sont appliquées à une vue et peuvent être relatives à une autre vue (faire en sorte que la hauteur d'une vue soit égale à une autre), ou fixer une dimension avec un nombre fixe (faire en sorte que la hauteur soit égale à 162).

Quelles informations recherchez-vous dans chaque contrainte ? 

  • La vue principale à laquelle elle s'applique

  • La dimension (hauteur, largeur, début, fin, haut, bas)

  • L'orientation (verticale ou horizontale)

  • Une vue secondaire à laquelle la contrainte est liée (facultatif)

  • La contrainte est constante. Le nombre réel à appliquer à la contrainte. Ce nombre peut également être négatif.

Exemples :

<NSLayoutConstraint:0x60000041c0f0 UIImageView:0x7fb5af855ea0.height == 164 (active)>

  • Fixer la hauteur de UIImageView à 164 points.

<NSLayoutConstraint:0x60000041c910 V:|-(9)-[UIStackView:0x7fb5af855810] (active, names: '|':UIView:0x7fb5af854ec0 )>

  • Appliquer un espace vertical de 9 points entre stackView et view.

<NSLayoutConstraint:0x60000041caa0 MyApp.FeaturedCollectionViewCell:0x7fb5af855bf0.top == UIView:0x7fb5af854ec0.top (active)>

  • Faire en sorte que le haut de FeaturedCollectionViewCell (classe de cellule personnalisée) égal au sommet de la vue.

<NSLayoutConstraint:0x6000004b2350 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600001ec7aa0'UIViewLayoutMarginsGuide']-(10)-| (active, names: '|':UIStackView:0x7fb59fd07360 )>

  • SLe bord inférieur de tackView doit être égal au guide de mise en page inférieur de la vue, plus 10 points.

Un exemple concret

(faisons le tour de la question)

Maintenant que nous sommes bien préparés, comment pouvons-nous résoudre de vrais problèmes de contraintes dans le monde réel ? J'ai créé un projet simple que vous pouvez télécharger ici pour déboguer 2 contraintes différentes.

Bienvenue à LayoutBeast (téléchargez-la ici), une simple application Xcode avec 1 contrôleur de vue et 4 sous-vues : blueView, blueLabel , orangeView, orangeLabel.

Asset - How To Debug NSLayoutConstraints (LayoutBeast) Blog Photo 2

Cependant, si vous exécutez l'application, vous constaterez que nous avons quelques problèmes. Jetons-y un coup d'œil :

Exemple 1

2022-10-04 10:42:27.022723-0400 LayoutBeast[98234:4811764] [LayoutConstraints] Unable to simultaneously satisfy constraints.

Il est probable qu'au moins une des contraintes de la liste suivante soit une contrainte que vous ne voulez pas.

Essayez ceci :

  1. Examinez chaque contrainte et essayez de trouver celle que vous n'attendez pas ;

  2. Trouvez le code qui a ajouté la ou les contraintes non désirées et corrigez-le.

(NOTE : Si vous voyez NSAutoresizingMaskLayoutConstraints que vous ne comprenez pas, consultez la documentation relative à la propriété UIView translatesAutoresizingMaskIntoConstraints)

Exemple 2

( "<NSAutoresizingMaskLayoutConstraint:0x60000236d4a0 h=--& v=--& an orange view.width == 0 (active, names: an orange view:0x7f796ff0bf90 )>", "<NSLayoutConstraint:0x6000023647d0 an orange view.width == 100 (active, names: an orange view:0x7f796ff0bf90 )>" )

Celui-ci n'est pas si mal ! Nous pouvons voir que nous avons quelques contraintes NSAutoresizingMaskLayoutConstraints ont été ajoutées à l'une de nos vues. Si nous regardons la note dans les logs, nous pouvons y voir un bon indice... Nous avons également parlé de cela dans notre section sur le contrôle d'intégrité, point 2.

Le problème semble venir du fait que nous n'avons pas défini le paramètre translatesAutoresizingMaskIntoConstraints à false dans l'une de nos vues. La solution sera donc d'ajouter cette ligne à notre méthode configureOrangeView() à notre méthode configureOrangeView() :

orangeView.translatesAutoresizingMaskIntoConstraints = false

Ahh, tout va bien maintenant ! Les choses vont beaucoup mieux maintenant. Et elles ont l'air mieux aussi :

Asset - How To Debug NSLayoutConstraints (LayoutBeast) Blog Photo 3

Causalité ou corrélation

Vous avez peut-être remarqué des icônes d'avertissement violettes à quelques endroits dans Xcode. Il s'agit d'avertissements d'exécution indiquant des problèmes de mise en page. C'est un autre endroit où vous pouvez recueillir des informations utiles sur l'endroit où les violations se produisent. Cependant, ces avertissements peuvent parfois être un peu trompeurs. Dans ce scénario spécifique, par exemple, ces avertissements sont les suivants N'EST PAS vous dire qui est responsable (causalité), mais plutôt quelles autres vues sont affectées (corrélation).

Asset - How To Debug NSLayoutConstraints (LayoutBeast) blog photo 4

En outre, si vous avez exécuté le projet, vous avez peut-être remarqué d'autres problèmes de contraintes dans nos journaux, juste en dessous de celui que nous avons cité ci-dessus. Ces problèmes indiquaient également les vues et les contraintes affectées, mais ils N'ÉTAIENT PAS vous indiquer la cause première.

Il s'agit de faire une distinction importante, qui ne s'applique pas seulement aux contraintes, mais à l'ingénierie en général :

Votre travail est toujours de trouver la cause première. Le cœur du problème. Tenter de résoudre quoi que ce soit d'autre ne résoudra pas le problème initial, plus profond.

CONSEIL : En regardant de plus près les journaux d'erreurs ci-dessus, vous verrez "une vue orange" dans les contraintes incriminées. Étrange... En y regardant de plus près, vous verrez également voir que nous définissons l'identifiant accessibilityIdentifier pour la vue orangeView à ce texte. Cela signifie que vous pouvez définir l'identifiant d'accessibilité d'une vue pour qu'elle soit imprimée lorsque vous rencontrez des conflits de contraintes. Cela a été SUPER SUPER utile pour moi !

Vous avez une question concernant cet article de blog ? Envoyez un courriel à l'auteur à julian.builes@improving.com ou contactez Improving ici! Si vous êtes un développeur à la recherche d'opportunités de carrière, jetez un coup d'œil à notre page carrières.

Technologie
Application Modernization

Dernières réflexions

Explorez nos articles de blog et laissez-vous inspirer par les leaders d'opinion de nos entreprises.
Blog Image - Unveiling the Future of AI at Google Cloud Next 24 -1
AI/ML

Unveiling the Future of AI at Google Cloud Next ‘24

Get firsthand insights from Improving into the innovation brewing around artificial intelligence and cloud computing at Google Cloud Next '24.