Vous êtes sur la page 1sur 129

AUTO LAYOUT

COCOAHEADS - MONTPELLIER - 12 MAI 2016


SOMMAIRE

Introduction
Comprendre l’Auto Layout
Utiliser l’Auto Layout
Maîtriser l’Auto Layout
Bonnes pratiques

13 MAI 2016 BACKELITE 2


INTRODUCTION
UTILISATION MULTI-CONTEXTE

L’interface utilisateur doit répondre dynamiquement


à 2 types de changements :

• changements externes

• changements internes

13 MAI 2016 BACKELITE 4


CHANGEMENTS EXTERNES

• Utilisateur redimensionne la fenêtre de l’application (OS X)


• Utilisateur ouvre / ferme le Split View sur un iPad
• La rotation de l’appareil
• L’apparition / disparition de la barre de status en mode (enregistrement,
appel en cours…)
• Le support de différentes catégories de tailles d’écran (size classes)
• Le support de différentes tailles d’écran

13 MAI 2016 BACKELITE 5


CHANGEMENTS INTERNES

• Le contenu affiché change


• Le support de l’internationalisation
• le support des types dynamiques

13 MAI 2016 BACKELITE 6


LES TROIS APPROCHES PRINCIPALES

Les Frames L’AutoresizingMask L’Auto Layout

7
LES FRAMES

Le calcul des frames : le moyen le plus flexible et le plus puissant

mais…

• ne supporte que les changements externes


• requiert un effort considérable pour designer, à débogguer et à maintenir
• l’effort augmente d'autant plus que l'interface doit être dynamique.

13 MAI 2016 BACKELITE 8


L’AUTORESIZINGMASK

Simplifie la création de mise en page (layout)


Permet d’alléger l’effort de design

mais…

• Ne convient que pour des agencements simples.


• Ne supporte que les changements externes.

13 MAI 2016 BACKELITE 9


L’AUTO LAYOUT

• Supporte les changements externes et internes.


• Gère une plus large palette d’agencement.
• Allége l’effort de design, de déboggage et de maintenance même pour les
mises en page complexe.

13 MAI 2016 BACKELITE 10


COMPRENDRE L'AUTO LAYOUT
QU’EST CE QUE L’AUTO LAYOUT ?

L’Auto Layout

est un système d’agencement, de Calcule dynamiquement la taille ainsi


mise en page, descriptif basé sur des que les dimensions de toutes les vues de
contraintes la hiérarchie en fonction de contraintes
placées sur ces vues.

13 MAI 2016 BACKELITE 12


ANATOMIE D’UNE CONTRAINTE

13 MAI 2016 BACKELITE 13


LES ATTRIBUTS

13 MAI 2016 BACKELITE 14


LES RELATIONS

// Egalité
Blue.leading = 1.0 * Red.trailing + 8.0

// Supériorité
View.width >= 0.0 * NotAnAttribute + 40.0

// Infériorité
View.width <= 0.0 * NotAnAttribute + 280.0

13 MAI 2016 BACKELITE 15


LES PRIORITÉS

• Priorité vont de 1 à 1000


• Required est 1000
• DefaultHigh est 750
• DefaultLow est 250
• Les priorités les plus fortes l’emporte

13 MAI 2016 BACKELITE 16


INTRINSIC CONTENT SIZE

• La plupart des vues n’ont pas de taille préfixée


• D’autres ont une taille prédéfinie
• sizeToFit
• sizeThatFits:
• Avec l’Auto Layout, cette taille se nomme l’intrinsicContentSize

13 MAI 2016 BACKELITE 17


INTRINSIC CONTENT SIZE

Vue Intrinsic Content Size

UIView -
UISlider Largeur
UILabels, UIButton, UISwitch,
Hauteur et largeur
UITextfield
UITextView, UIImageView Peut varié

13 MAI 2016 BACKELITE 18


INTRINSIC CONTENT SIZE

• intrinsicContentSize() est mieux que sizeToFit()


• Appeler invalidateIntrinsicContentSize() à chaque que l’intrinsicContentSize
doit être recalculé

public func intrinsicContentSize() -> CGSize

public func invalidateIntrinsicContentSize()

13 MAI 2016 BACKELITE 19


INTRINSIC CONTENT SIZE

• L’intrinsicContentSize génère deux contraintes par dimensions

13 MAI 2016 BACKELITE 20


INTRINSIC CONTENT SIZE

• L’intrinsicContentSize génère deux contraintes par dimensions

view.height >= 0.0 x NotAnAttribute + intrinsicContentSize.height

view.height <= 0.0 x NotAnAttribute + intrinsicContentSize.height

13 MAI 2016 BACKELITE 21


INTRINSIC CONTENT SIZE

• L’intrinsicContentSize génère deux contraintes par dimensions

view.height >= 0.0 x NotAnAttribute + intrinsicContentSize.height


view.width >= 0.0 x NotAnAttribute + intrinsicContentSize.width

view.height <= 0.0 x NotAnAttribute + intrinsicContentSize.height


view.width <= 0.0 x NotAnAttribute + intrinsicContentSize.width

13 MAI 2016 BACKELITE 22


INTRINSIC CONTENT SIZE

• L’intrinsicContentSize génère deux contraintes par dimensions

Content Compression Resistance


view.height >= 0.0 x NotAnAttribute + intrinsicContentSize.height
view.width >= 0.0 x NotAnAttribute + intrinsicContentSize.width

view.height <= 0.0 x NotAnAttribute + intrinsicContentSize.height


view.width <= 0.0 x NotAnAttribute + intrinsicContentSize.width

13 MAI 2016 BACKELITE 23


INTRINSIC CONTENT SIZE

• L’intrinsicContentSize génère deux contraintes par dimensions

Content Compression Resistance


view.height >= 0.0 x NotAnAttribute + intrinsicContentSize.height
view.width >= 0.0 x NotAnAttribute + intrinsicContentSize.width

Content Hugging
view.height <= 0.0 x NotAnAttribute + intrinsicContentSize.height
view.width <= 0.0 x NotAnAttribute + intrinsicContentSize.width

13 MAI 2016 BACKELITE 24


CONTENT HUGGING & CONTENT COMPRESSION

13 MAI 2016 BACKELITE 25


CONTENT HUGGING & CONTENT COMPRESSION

• Il est possible de modifier leur priorités

func setContentHuggingPriority(priority: UILayoutPriority,


forAxis axis: UILayoutConstraintAxis)

func setContentCompressionResistancePriority(priority: UILayoutPriority,


forAxis axis: UILayoutConstraintAxis)

13 MAI 2016 BACKELITE 26


LE PROCESSUS D’AGENCEMENT

Vues

Contraintes
Moteur Mise
d’agencement en page
(layout engine) (layout)
Priorités

intrinsic
ContentSize

13 MAI 2016 BACKELITE 27


LE PROCESSUS D’AGENCEMENT

Constraints
change

Application Update
Run Loop Pass

Layout
Display
Pass

13 MAI 2016 BACKELITE 28


LE PROCESSUS D’AGENCEMENT

Les changements d’une contrainte


• activation / désactivation
• changement de la constant ou de la priorité
• suppression de la vue dans la hiérarchie

Le moteur d’agencement recalcule la mise en page :


• lorsqu’il reçoit de nouvelles valeurs
• Les vues appellent superview.setNeedsLayout()

13 MAI 2016 BACKELITE 29


LE PROCESSUS D’AGENCEMENT

updateConstraintes est appelé


• A chaque cycle du moteur d’agencement
• Lorsqu’on fait appel à setNeedsUpdateConstraintes()

Overrider lorsque :
• Les changements des contraintes est trop lents
• Une vue fait régulièrement des changements sur ses contraintes
• Appel du super à la fin de la méthode

13 MAI 2016 BACKELITE 30


LE PROCESSUS D’AGENCEMENT

La phase de Layout

Traverse la hiérarchie de vue de haut en bas


• Appel à layoutSubviews()

Positionne les frames de chaque sous-vue


• Copie les frames venant du moteur d’agencement

13 MAI 2016 BACKELITE 31


LES PROBLÈMES QUE L’ON PEUT RENCONTRER

Layout ambiguë : plusieurs agencements sont possibles


• Pas assez de contraintes
• Contraintes optionnels dont la priorité sont égales

Layout insatisfait : aucun agencement possible


• Certaines contraintes se contredisent

13 MAI 2016 BACKELITE 32


UTILISER L'AUTO LAYOUT
VIA INTERFACE BUILDER

Le canvas permet :

• de créer rapidement, via un clique


droit + glisser, une contrainte entre
deux vue.

13 MAI 2016 BACKELITE 34


VIA INTERFACE BUILDER

Le panneau « Structure de
document » permet :

• de lister les contraintes


• de créer via un clique droit +
glisser rapidement des
contraintes entre deux vues.

13 MAI 2016 BACKELITE 35


VIA INTERFACE BUILDER

L’outil d’alignement permet de


rapidement ajouter des contraintes
sur les centres et les bordures

13 MAI 2016 BACKELITE 36


VIA INTERFACE BUILDER

L’outils de résolutions des


problèmes d’Auto Layout permet :

• d’ajouter les contraintes


manquantes
• de repositionner et
redimensionner les vues mal
positionnées
• de faire une remise à zéro des
contraintes
• de supprimer tous les contraintes

13 MAI 2016 BACKELITE 37


VIA INTERFACE BUILDER

L’inspecteur de taille permet :

• de lister toutes les contraintes


qui affectent la vue
sélectionnée.
• de filtrer les contraintes suivant
les classes de tailles.
• de filtrer les contraintes par leur
type attributs (leading, trailing…)

13 MAI 2016 BACKELITE 38


VIA INTERFACE BUILDER

L’inspecteur de taille permet :

• de modifier rapidement la
constante, la relation et la
priorité d’une contrainte

13 MAI 2016 BACKELITE 39


VIA INTERFACE BUILDER

L’inspecteur d’attributs permet :

• de modifier la relation, la
priorité, la constante, le
multiplier de la contrainte
• d’intervertir le premier et le
deuxième élément
• de marquer la contrainte comme
fictive

13 MAI 2016 BACKELITE 40


VIA INTERFACE BUILDER

L’inspecteur d’attributs permet :

• de modifier les priorités des


content hugging et content
compression
• de définir une largeur et une
hauteur fictives pour le contenu
(intrinsicContentSize)

13 MAI 2016 BACKELITE 41


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

public convenience init(item view1: AnyObject,


attribute attr1: NSLayoutAttribute,
relatedBy relation: NSLayoutRelation,
toItem view2: AnyObject?,
attribute attr2: NSLayoutAttribute,
multiplier: CGFloat,
constant c: CGFloat)

13 MAI 2016 BACKELITE 42


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 43


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 44


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 45


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 46


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = 1.0 x superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 47


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 48


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 49


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.centerX = superview.centerX + 0.0

NSLayoutConstraint(item: button, attribute: .CenterX,


relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)

13 MAI 2016 BACKELITE 50


VIA LE CODE

item1.attribute1 = multiplier x item2.attribute2 + constant

• button.bottom = superview.bottom - <padding>

NSLayoutConstraint(item: button, attribute: .Bottom,


relatedBy: .Equal,
toItem: superview, attribute: .Bottom,
multiplier: 1.0,
constant: -padding)

13 MAI 2016 BACKELITE 51


NSLAYOUTANCHOR

• Simplifie la création de contrainte


• Facilite la lisibilité

NSLayoutConstraint(item:b, attribute: .Top, relatedBy: .Equal, toItem:view,


attribute:.Top, multiplier:1, constant:10)

NSLayoutConstraint(item:b, attribute:.Leading, relatedBy:.Equal,


toItem:view, attribute:.Leading, multiplier:1, constant:10)

b.topAnchor.constraintEqualToAnchor(view.topAnchor, constant:10)

b.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant:10)

13 MAI 2016 BACKELITE 52


NSLAYOUTANCHOR

• Empêche la création de contrainte invalide

v1.leadingAnchor.constraintEqualToConstant(100)
// Error: may not respond to method

v1.leadingAnchor.constraintEqualToAnchor(v2.widthAnchor)
// Error: incompatible pointer type

13 MAI 2016 BACKELITE 53


LE LANGUAGE DU FORMAT VISUEL

• Simplifie la création de contraintes


• Facilite la lisibilité
• Supporte les relations, les priorités, les alignements

13 MAI 2016 BACKELITE 54


LE LANGUAGE DU FORMAT VISUEL

cancelButton acceptButton

13 MAI 2016 BACKELITE 55


LE LANGUAGE DU FORMAT VISUEL

[cancelButton]-[acceptButton]

13 MAI 2016 BACKELITE 56


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton]-[acceptButton]",
options: [], metrics: nil, views: viewsDictionary)

13 MAI 2016 BACKELITE 57


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton]-[acceptButton]",
options: [], metrics: nil, views: viewsDictionary)

let cancelButton: UIButton = …


let acceptButton: UIButton = …
let viewsDictionary = ["cancelButton": cancelButton,
"acceptButton": acceptButton]

13 MAI 2016 BACKELITE 58


LE LANGUAGE DU FORMAT VISUEL

[cancelButton]-[acceptButton]

13 MAI 2016 BACKELITE 59


LE LANGUAGE DU FORMAT VISUEL

[cancelButton ]— -[acceptButton ]

13 MAI 2016 BACKELITE 60


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72)]—12-[acceptButton(50)]

13 MAI 2016 BACKELITE 61


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72 )]—12-[acceptButton(50)]

13 MAI 2016 BACKELITE 62


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72@250)]—12-[acceptButton(50)]

13 MAI 2016 BACKELITE 63


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72@250)]—12-[acceptButton(50)]

13 MAI 2016 BACKELITE 64


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72@250)]—12-[acceptButton( 50)]

13 MAI 2016 BACKELITE 65


LE LANGUAGE DU FORMAT VISUEL

[cancelButton(72@250)]—12-[acceptButton(>=50)]

13 MAI 2016 BACKELITE 66


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—12-[acceptButton(>=50)]",
options: [], metrics: nil, views: viewsDictionary)

13 MAI 2016 BACKELITE 67


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—( )-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)

13 MAI 2016 BACKELITE 68


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)

13 MAI 2016 BACKELITE 69


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@ )]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)

13 MAI 2016 BACKELITE 70


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@p)]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)

let metricsDictionary = ["spacing": 12,


"p": 250]

13 MAI 2016 BACKELITE 71


LE LANGUAGE DU FORMAT VISUEL

[cancelButton]-[acceptButton]

13 MAI 2016 BACKELITE 72


LE LANGUAGE DU FORMAT VISUEL

[cancelButton]-[acceptButton ]

13 MAI 2016 BACKELITE 73


LE LANGUAGE DU FORMAT VISUEL

[cancelButton]-[acceptButton(==cancelButton)]

13 MAI 2016 BACKELITE 74


LE LANGUAGE DU FORMAT VISUEL

|[cancelButton]-[acceptButton(==cancelButton)]|

13 MAI 2016 BACKELITE 75


LE LANGUAGE DU FORMAT VISUEL

| [cancelButton]-[acceptButton(==cancelButton)] |

13 MAI 2016 BACKELITE 76


LE LANGUAGE DU FORMAT VISUEL

|-[cancelButton]-[acceptButton(==cancelButton)]-|

13 MAI 2016 BACKELITE 77


LE LANGUAGE DU FORMAT VISUEL

|- -[cancelButton]-[acceptButton(==cancelButton)]- -|

13 MAI 2016 BACKELITE 78


LE LANGUAGE DU FORMAT VISUEL

|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|

13 MAI 2016 BACKELITE 79


LE LANGUAGE DU FORMAT VISUEL

H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|

13 MAI 2016 BACKELITE 80


LE LANGUAGE DU FORMAT VISUEL

H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|

13 MAI 2016 BACKELITE 81


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: [], metrics: metricsDictionary, views: viewsDictionary)

13 MAI 2016 BACKELITE 82


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: options, metrics: metricsDictionary, views: viewsDictionary)

let options: NSLayoutFormatOptions = .AlignAllTop

13 MAI 2016 BACKELITE 83


LE LANGUAGE DU FORMAT VISUEL

NSLayoutConstraint.constraintsWithVisualFormat(
"V:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: options, metrics: metricsDictionary, views: viewsDictionary)

let options: NSLayoutFormatOptions = .AlignAllCenterX

13 MAI 2016 BACKELITE 84


AJOUT DE CONTRAINTES

• Méthodes sur UIView

// ajout
public func addConstraint(constraint: NSLayoutConstraint)
public func addConstraints(constraints: [NSLayoutConstraint])

// suppression
public func removeConstraint(constraint: NSLayoutConstraint)
public func removeConstraints(constraints: [NSLayoutConstraint])

13 MAI 2016 BACKELITE 85


AJOUT DE CONTRAINTES

translatesAutoresizingMaskIntoConstraints
• convertit les frames en contraintes
• est à true pour les contraintes créer via le code

• Si on utilise les frames, le mettre à true


• Sinon ne pas oublier de le mettre a false !

v1.translatesAutoresizingMaskIntoConstraints = false

13 MAI 2016 BACKELITE 86


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 87


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 88


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 89


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 90


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 91


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 92


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 93


AJOUT DE CONTRAINTES

Sur quelle vue ajouter les


contraintes ?

13 MAI 2016 BACKELITE 94


ACTIVATION / DÉSACTIVATION DE CONTRAINTES

• Méthodes sur NSLayoutConstraint

// activation - désactivation
+ (void)activateConstraints:(NSArray *)constraint;
+ (void)deactivateConstraints:(NSArray *)constraint;

13 MAI 2016 BACKELITE 95


AUTO LAYOUT ET LES LABELS

UILabel multi-ligne :
• Mettre le nombre de ligne à 0
• preferredMaxLayoutWidth indique la largeur pour le retour à la ligne
• Ajuster les priorités de content hugging et content compression

< iOS 8 :
• preferredMaxLayoutWidth != frame
• doit mettre la jour preferredMaxLayoutWidth à la main

13 MAI 2016 BACKELITE 96


AUTO LAYOUT ET SCROLLVIEW

• Défini la contentSize de la scrollView


• L’ensemble des contraintes doit relier les bords de la scrollview
• Utilise une contentView pour facilité la création du layout
• Scroll horizontal : contentView.width > scrollview.width
• Scroll vertical : contentView.height > scrollview.height

13 MAI 2016 BACKELITE 97


AUTO LAYOUT ET SCROLLVIEW

UIScrollview

ContentView

View View

View

View

13 MAI 2016 BACKELITE 98


ANIMATION

// Ensures that all pending layout operations have been


completed
containerView.layoutIfNeeded()

UIView.animateWithDuration(1.0) {
// Make all constraint changes here
myConstraint.constant = 0.0
// Forces the layout of the subtree animation block
// and then captures all of the frame changes
containerView.layoutIfNeeded()
}

13 MAI 2016 BACKELITE 99


MAÎTRISER L'AUTO LAYOUT
COMPRENDRE LES LOGS DE LA CONSOLE

Unable to simultaneously satisfy constraints.


Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7fff2b5b1050 H:[UIButton:0x7fff2b5ad100'Envoyer'(200)]>",
"<NSLayoutConstraint:0x7fff2b5b0550 UITextField:0x7fff2b5a34a0.leading == UIView:
0x7fff2b5a3e70.leadingMargin>",
"<NSLayoutConstraint:0x7fff2b5b0be0 H:[UITextField:0x7fff2b5a34a0(>=250)]>",
"<NSLayoutConstraint:0x7fff2b5b0d40 H:[UITextField:0x7fff2b5a34a0]-(NSSpace(8))-[UIButton:
0x7fff2b5ad100'Envoyer']>",
"<NSLayoutConstraint:0x7fff2b5b0e00 UIView:0x7fff2b5a3e70.trailingMargin == UIButton:
0x7fff2b5ad100'Envoyer'.trailing>",
"<NSLayoutConstraint:0x7fff2b646d30 'UIView-Encapsulated-Layout-Width' H:[UIView:
0x7fff2b5a3e70(414)]>"
)

Will attempt to recover by breaking constraint


<NSLayoutConstraint:0x7fff2b5b1050 H:[UIButton:0x7fff2b5ad100'Envoyer'(200)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may
also be helpful.

13 MAI 2016 BACKELITE 101


COMPRENDRE LES LOGS DE LA CONSOLE

Unable to simultaneously satisfy constraints.


Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7fff2b5b1050 H:[UIButton:0x7fff2b5ad100'Envoyer'(200)]>",
"<NSLayoutConstraint:0x7fff2b5b0550 UITextField:0x7fff2b5a34a0.leading == UIView:
0x7fff2b5a3e70.leadingMargin>",
"<NSLayoutConstraint:0x7fff2b5b0be0 H:[UITextField:0x7fff2b5a34a0(>=250)]>",
"<NSLayoutConstraint:0x7fff2b5b0d40 H:[UITextField:0x7fff2b5a34a0]-(NSSpace(8))-[UIButton:
0x7fff2b5ad100'Envoyer']>",
"<NSLayoutConstraint:0x7fff2b5b0e00 UIView:0x7fff2b5a3e70.trailingMargin == UIButton:
0x7fff2b5ad100'Envoyer'.trailing>",
"<NSLayoutConstraint:0x7fff2b646d30 'UIView-Encapsulated-Layout-Width' H:[UIView:
0x7fff2b5a3e70(414)]>"
)

Will attempt to recover by breaking constraint


<NSLayoutConstraint:0x7fff2b5b1050 H:[UIButton:0x7fff2b5ad100'Envoyer'(200)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may
also be helpful.

13 MAI 2016 BACKELITE 102


COMPRENDRE LES LOGS DE LA CONSOLE

Unable to simultaneously satisfy constraints.


Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7ff6da1803e0 H:[sendButton(200)] (Names: sendButton:0x7ff6da17b940 )>",
"<NSLayoutConstraint:0x7ff6da17f1e0 messageTextField.leading == Superview.leadingMargin (Names:
messageTextField:0x7ff6da145570, Superview:0x7ff6da173c20 )>",
"<NSLayoutConstraint:0x7ff6da17fd70 H:[messageTextField(>=250)] (Names: messageTextField:
0x7ff6da145570 )>",
"<NSLayoutConstraint:0x7ff6da17fed0 H:[messageTextField]-(NSSpace(8))-[sendButton] (Names:
sendButton:0x7ff6da17b940, messageTextField:0x7ff6da145570 )>",
"<NSLayoutConstraint:0x7ff6da180190 Superview.trailingMargin == sendButton.trailing (Names:
Superview:0x7ff6da173c20, sendButton:0x7ff6da17b940 )>",
"<NSLayoutConstraint:0x7ff6d8c1c780 'UIView-Encapsulated-Layout-Width' H:[Superview(414)] (Names:
Superview:0x7ff6da173c20 )>"
)

Will attempt to recover by breaking constraint


<NSLayoutConstraint:0x7ff6da1803e0 H:[sendButton(200)] (Names: sendButton:0x7ff6da17b940 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may
also be helpful.

13 MAI 2016 BACKELITE 103


COMPRENDRE LES LOGS DE LA CONSOLE

Unable to simultaneously satisfy constraints.


Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7fbeabc50340 messageTextField.leading == Superview.leadingMargin (Names:
messageTextField:0x7fbeabc31020, Superview:0x7fbeabc43ce0 )>",
"<NSLayoutConstraint:0x7fbeabc509b0 H:[messageTextField(>=250)] (Names: messageTextField:0x7fbeabc31020 )>",
"<NSLayoutConstraint:0x7fbeabc50b10 H:[messageTextField]-(NSSpace(8))-[sendButton] (Names: sendButton:
0x7fbeabc4ce10, messageTextField:0x7fbeabc31020 )>",
"<NSLayoutConstraint:0x7fbeabc50bd0 Superview.trailingMargin == sendButton.trailing (Names: Superview:
0x7fbeabc43ce0, sendButton:0x7fbeabc4ce10 )>",
"<NSLayoutConstraint:0x7fbeabc50e20 'fixedWidthLayout' H:[sendButton(200)] (Names: sendButton:
0x7fbeabc4ce10 )>",
"<NSLayoutConstraint:0x7fbead92e6d0 'UIView-Encapsulated-Layout-Width' H:[Superview(414)] (Names: Superview:
0x7fbeabc43ce0 )>"
)

Will attempt to recover by breaking constraint


<NSLayoutConstraint:0x7fbeabc50e20 'fixedWidthLayout' H:[sendButton(200)] (Names: sendButton:0x7fbeabc4ce10 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be
helpful.

13 MAI 2016 BACKELITE 104


COMPRENDRE LES LOGS DE LA CONSOLE

Unable to simultaneously satisfy constraints.


Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the
documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x7ff2e5243430 h=--& v=--& messageTextField.midY == (Names:
messageTextField:0x7ff2e522e700 )>",
"<NSAutoresizingMaskLayoutConstraint:0x7ff2e52432b0 h=--& v=--& V:[messageTextField(0)] (Names:
messageTextField:0x7ff2e522e700 )>",
"<NSLayoutConstraint:0x7ff2e522ad40 V:[messageTextField]-(20)-| (Names: Superview:0x7ff2e522bcf0,
messageTextField:0x7ff2e522e700, '|':Superview:0x7ff2e522bcf0 )>",
"<NSLayoutConstraint:0x7ff2e354dc70 'UIView-Encapsulated-Layout-Height' V:[Superview(736)] (Names: Superview:
0x7ff2e522bcf0 )>",
"<NSAutoresizingMaskLayoutConstraint:0x7ff2e3567470 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' V:|-(0)-
[Superview] (Names: Superview:0x7ff2e522bcf0, '|':UIWindow:0x7ff2e522b7c0 )>"
)

Will attempt to recover by breaking constraint


<NSLayoutConstraint:0x7ff2e522ad40 V:[messageTextField]-(20)-| (Names: Superview:0x7ff2e522bcf0, messageTextField:
0x7ff2e522e700, '|':Superview:0x7ff2e522bcf0 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.


The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be
helpful.

13 MAI 2016 BACKELITE 105


COMPRENDRE LES LOGS DE LA CONSOLE

Ajout d’identifiants sur les contraintes

labelToTop.identifier = "labelToTop"

Ajout d’identifiants d’accessibilité sur les vues

titleLabel.accessibilityIdentifier = "titleLabel"

Désactiver le translateAutoresizingMaskIntoConstraints

sendButton.translatesAutoresizingMaskIntoConstraints = false

13 MAI 2016 BACKELITE 106


DETECTION DES LAYOUTS AMBIGUS

• hasAmbigousLayout
retourne vrai si la vue a sa frame mal placé
• exerciceAmbiguityInLayout
commute entre les différentes possibilité de layout
• constraintAffectingLayoutForAxis
return la liste des contraintes associés à un axe
• _autolayoutTrace
affiche un diagnostique sur la hiérarchie de vue entière

13 MAI 2016 BACKELITE 107


RÉSOUDRE LES LAYOUTS AMBIGUS

• Ajout de contraintes supplémentaires


• Mais ce n’est pas toujours le cas
• Modification des priorités des contraintes existantes
Content Hugging, Content Compression

13 MAI 2016 BACKELITE 108


DÉSACTIVER LE SCROLL VERTICAL D’UNE SCROLLVIEW

UIScrollview 0

ContentView

View View =
=

View

View

13 MAI 2016 BACKELITE 109


DÉSACTIVER LE SCROLL HORIZONTAL D’UNE SCROLLVIEW

UIScrollview

ContentView

View View

0 0
View

View

=
=

13 MAI 2016 BACKELITE 110


VUE FLOTTANTE DANS UNE SCROLLVIEW

UIScrollview Container 0

UIScrollview

ContentView
0
View View

View

0
View
View
flottante

13 MAI 2016 BACKELITE 111


LE SPLIT VIEW

Split View 0 0

Master View Detail View

0
0 0

= 1/3 =x3

0 0

13 MAI 2016 BACKELITE 112


LE SPLIT VIEW

Split View 0

Master View Detail View

0
0 0

= 1/3 =x3

13 MAI 2016 BACKELITE 113


RÉPARTITION DE VUES DE MÊME TAILLE SUR UN AXE

Superview

Vue 1 Vue 2 Vue 3 Vue 4

= = = =
=
=

13 MAI 2016 BACKELITE 114


RÉPARTITION DE VUES DE MÊME TAILLE SUR UN AXE

Superview

Vue 1 Vue 2 Vue 3 Vue 4

= = = =
= =

13 MAI 2016 BACKELITE 115


RÉPARTITION DE VUES AVEC ESPACEMENT DE MÊME TAILLE SUR UN AXE

Superview

Vue 1 Vue 2 Vue 3

= = = =
=
=

13 MAI 2016 BACKELITE 116


CENTRER UN GROUPE DE VUES

Superview

Conteneur 0

Vue
Vue 0

Vue
0 Vue

13 MAI 2016 BACKELITE 117


UILAYOUTGUIDE

• Définie un rectangle qui peut interagir avec le moteur d’agencement.


• Remplace les dummy views

let space1 = UILayoutGuide()


view.addLayoutGuide(space1)

let space2 = UILayoutGuide()


view.addLayoutGuide(space2)

space1.widthAnchor.constraintEqualToAnchor(space2.widthAnchor).active = true

saveButton.trailingAnchor.constraintEqualToAnchor(space1.leadingAnchor).active = true
cancelButton.leadingAnchor.constraintEqualToAnchor(space1.trailingAnchor).active = true
cancelButton.trailingAnchor.constraintEqualToAnchor(space2.leadingAnchor).active = true
clearButton.leadingAnchor.constraintEqualToAnchor(space2.trailingAnchor).active = true

13 MAI 2016 BACKELITE 118


UILAYOUTGUIDE

• Définie un rectangle qui peut interagir avec le moteur d’agencement.


• Remplace les dummy views

let space1 = UILayoutGuide()


view.addLayoutGuide(space1)

let space2 = UILayoutGuide()


view.addLayoutGuide(space2)

NSLayoutConstraint.constraintsWithVisualFormat(
"H:[saveButton][space1][cancelButton][space2(==space1)][clearButton]",
options: .AlignAllBaseline, metrics: nil, views: views)

13 MAI 2016 BACKELITE 119


TOP/BOTTOM LAYOUT GUIDE

• Représente le bord du haut et du bas de la surface visible du viewController


courant
• En dessous de la statusBar ou navigationBar
• Au dessus de tabBar

13 MAI 2016 BACKELITE 120


LAYOUT MARGINS GUIDE

• Représente les marges de la vue


• Utilise les valeurs le la propriété layoutMargins
• Marges de 8 points par défaut sur chaque bord
• Les marges de la vue racine d’un contrôleur ne sont pas modifiable

13 MAI 2016 BACKELITE 121


READABLE CONTENT GUIDE

• Définie la largeur maximal pour le texte


• Dépends de la taille du type dynamique
• Reste toujours entre les margins

13 MAI 2016 BACKELITE 122


SEMANTIC CONTENT ATTRIBUTES

• Détermine lorsque si la vue doit basculer lors d’un changement du sens de la


lecture
• Les position Leading et trailing s’inversent
• Alors que Top, Bottom, Left et Right ne bouge pas

13 MAI 2016 BACKELITE 123


BONNES PRATIQUES
BONNES PRATIQUES

• Ne plus utiliser les frames, bounds ou center pour changer les dimensions et
la position de la vue
• Éviter de donner un largeur et longueur fixe à une vue
• Donner des noms qui ont du sens à vos vues
• Toujours utiliser Leading et Trailing
• translateAutoresizingMaskIntoConstraints = NO
• Utiliser les layoutMarginsGuides
• Utiliser les readableContentGuides pour les textes

13 MAI 2016 BACKELITE 125


BONNES PRATIQUES

• Utiliser les topLayoutGuide et BottomLayoutGuide lorsque la vue s’étend


sous les bars
• Evitez d’overrider le layoutSubviews()
• Ne pensez plus frames mais relations
• Activer / Désactiver les contraintes au lieu de les ajouter / retirer
• Utiliser les baselines au lieu de top/bottom
• Déterminer la taille d’un composant via ses contraintes
• Override intrinsicContentSize judicieusement

13 MAI 2016 BACKELITE 126


BONNES PRATIQUES

• Utiliser les priorités pour résoudre votre layout


• Garder en tête la localisation
• Overrider updateContraints judicieusement
• Ne jamais désactiver toutes les contraintes : self.view.constraints

13 MAI 2016 BACKELITE 127


QUELQUES LIENS

Références

Auto Layout Guide https://developer.apple.com/library/ios/documentation/UserExperience/


Conceptual/AutolayoutPG/index.html#//apple_ref/doc/uid/TP40010853-CH7-
SW1

Adopting Auto https://developer.apple.com/library/watchos/documentation/UserExperience/


Layout Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html#//
apple_ref/doc/uid/TP40010853-CH5-SW7

Mysteries of Auto https://developer.apple.com/videos/play/wwdc2015/218/


Layout, Part 1

Mysteries of Auto https://developer.apple.com/videos/play/wwdc2015/219/


Layout, Part 2

13 MAI 2016 BACKELITE 128


CONTACTEZ-NOUS
Mickael Laloum
iOS Lead Developer

mickael.laloum@backelite.com

www.backelite.com

13 MAI 2016 BACKELITE 129

Vous aimerez peut-être aussi