4. 13 MAI 2016 BACKELITE
UTILISATION MULTI-CONTEXTE
L’interface utilisateur doit répondre dynamiquement
à 2 types de changements :
• changements externes
• changements internes
4
5. 13 MAI 2016 BACKELITE
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
5
6. 13 MAI 2016 BACKELITE
CHANGEMENTS INTERNES
• Le contenu affiché change
• Le support de l’internationalisation
• le support des types dynamiques
6
7. LES TROIS APPROCHES PRINCIPALES
7
Les Frames L’AutoresizingMask L’Auto Layout
8. 13 MAI 2016 BACKELITE
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.
8
9. 13 MAI 2016 BACKELITE
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.
9
10. 13 MAI 2016 BACKELITE
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.
10
12. 13 MAI 2016 BACKELITE
QU’EST CE QUE L’AUTO LAYOUT ?
L’Auto Layout
est un système d’agencement, de
mise en page, descriptif basé sur des
contraintes
12
Calcule dynamiquement la taille ainsi
que les dimensions de toutes les vues de
la hiérarchie en fonction de contraintes
placées sur ces vues.
13. 13 MAI 2016 BACKELITE
ANATOMIE D’UNE CONTRAINTE
13
16. 13 MAI 2016 BACKELITE
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
16
17. 13 MAI 2016 BACKELITE
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
17
18. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
18
Vue Intrinsic Content Size
UIView -
UISlider Largeur
UILabels, UIButton, UISwitch,
UITextfield
Hauteur et largeur
UITextView, UIImageView Peut varié
19. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• intrinsicContentSize() est mieux que sizeToFit()
• Appeler invalidateIntrinsicContentSize() à chaque que l’intrinsicContentSize
doit être recalculé
19
public func intrinsicContentSize() -> CGSize
public func invalidateIntrinsicContentSize()
20. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• L’intrinsicContentSize génère deux contraintes par dimensions
20
21. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• L’intrinsicContentSize génère deux contraintes par dimensions
21
view.height >= 0.0 x NotAnAttribute + intrinsicContentSize.height
view.height <= 0.0 x NotAnAttribute + intrinsicContentSize.height
22. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• L’intrinsicContentSize génère deux contraintes par dimensions
22
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
23. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• L’intrinsicContentSize génère deux contraintes par dimensions
23
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
Content Compression Resistance
24. 13 MAI 2016 BACKELITE
INTRINSIC CONTENT SIZE
• L’intrinsicContentSize génère deux contraintes par dimensions
24
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
Content Compression Resistance
Content Hugging
26. 13 MAI 2016 BACKELITE
CONTENT HUGGING & CONTENT COMPRESSION
• Il est possible de modifier leur priorités
26
func setContentHuggingPriority(priority: UILayoutPriority,
forAxis axis: UILayoutConstraintAxis)
func setContentCompressionResistancePriority(priority: UILayoutPriority,
forAxis axis: UILayoutConstraintAxis)
27. 13 MAI 2016 BACKELITE
LE PROCESSUS D’AGENCEMENT
27
Vues
Contraintes
Priorités
intrinsic
ContentSize
Moteur
d’agencement
(layout engine)
Mise
en page
(layout)
28. 13 MAI 2016 BACKELITE
LE PROCESSUS D’AGENCEMENT
28
Constraints
change
Update
Pass
Layout
Pass
Display
Application
Run Loop
29. 13 MAI 2016 BACKELITE
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()
29
30. 13 MAI 2016 BACKELITE
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
30
31. 13 MAI 2016 BACKELITE
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
31
32. 13 MAI 2016 BACKELITE
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
32
34. 13 MAI 2016 BACKELITE
VIA INTERFACE BUILDER
Le canvas permet :
• de créer rapidement, via un clique
droit + glisser, une contrainte entre
deux vue.
34
35. 13 MAI 2016 BACKELITE
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.
35
36. 13 MAI 2016 BACKELITE
VIA INTERFACE BUILDER
L’outil d’alignement permet de
rapidement ajouter des contraintes
sur les centres et les bordures
36
37. 13 MAI 2016 BACKELITE
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
37
38. 13 MAI 2016 BACKELITE
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…)
38
39. 13 MAI 2016 BACKELITE
VIA INTERFACE BUILDER
L’inspecteur de taille permet :
• de modifier rapidement la
constante, la relation et la
priorité d’une contrainte
39
40. 13 MAI 2016 BACKELITE
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
40
41. 13 MAI 2016 BACKELITE
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)
41
42. 13 MAI 2016 BACKELITE
VIA LE CODE
item1.attribute1 = multiplier x item2.attribute2 + constant
42
public convenience init(item view1: AnyObject,
attribute attr1: NSLayoutAttribute,
relatedBy relation: NSLayoutRelation,
toItem view2: AnyObject?,
attribute attr2: NSLayoutAttribute,
multiplier: CGFloat,
constant c: CGFloat)
43. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
43
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
44. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
44
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
45. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
45
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
46. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
46
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
47. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = 1.0 x superview.centerX
47
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
48. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
48
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
49. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX
49
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
50. 13 MAI 2016 BACKELITE
VIA LE CODE
• button.centerX = superview.centerX + 0.0
50
NSLayoutConstraint(item: button, attribute: .CenterX,
relatedBy: .Equal,
toItem: superview, attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
item1.attribute1 = multiplier x item2.attribute2 + constant
51. 13 MAI 2016 BACKELITE
• button.bottom = superview.bottom - <padding>
NSLayoutConstraint(item: button, attribute: .Bottom,
relatedBy: .Equal,
toItem: superview, attribute: .Bottom,
multiplier: 1.0,
constant: -padding)
VIA LE CODE
51
item1.attribute1 = multiplier x item2.attribute2 + constant
52. 13 MAI 2016 BACKELITE
NSLAYOUTANCHOR
• Simplifie la création de contrainte
• Facilite la lisibilité
52
b.topAnchor.constraintEqualToAnchor(view.topAnchor, constant:10)
b.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant:10)
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)
53. 13 MAI 2016 BACKELITE
NSLAYOUTANCHOR
• Empêche la création de contrainte invalide
53
v1.leadingAnchor.constraintEqualToConstant(100)
// Error: may not respond to method
v1.leadingAnchor.constraintEqualToAnchor(v2.widthAnchor)
// Error: incompatible pointer type
54. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
• Simplifie la création de contraintes
• Facilite la lisibilité
• Supporte les relations, les priorités, les alignements
54
55. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
55
cancelButton acceptButton
56. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
56
[cancelButton]-[acceptButton]
57. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
57
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton]-[acceptButton]",
options: [], metrics: nil, views: viewsDictionary)
58. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
58
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton]-[acceptButton]",
options: [], metrics: nil, views: viewsDictionary)
let cancelButton: UIButton = …
let acceptButton: UIButton = …
let viewsDictionary = ["cancelButton": cancelButton,
"acceptButton": acceptButton]
59. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
59
[cancelButton]-[acceptButton]
60. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
60
[cancelButton ]— -[acceptButton ]
61. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
61
[cancelButton(72)]—12-[acceptButton(50)]
62. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
62
[cancelButton(72 )]—12-[acceptButton(50)]
63. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
63
[cancelButton(72@250)]—12-[acceptButton(50)]
64. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
64
[cancelButton(72@250)]—12-[acceptButton(50)]
65. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
65
[cancelButton(72@250)]—12-[acceptButton( 50)]
66. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
66
[cancelButton(72@250)]—12-[acceptButton(>=50)]
67. 13 MAI 2016 BACKELITE
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—12-[acceptButton(>=50)]",
options: [], metrics: nil, views: viewsDictionary)
LE LANGUAGE DU FORMAT VISUEL
67
68. 13 MAI 2016 BACKELITE
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—( )-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)
LE LANGUAGE DU FORMAT VISUEL
68
69. 13 MAI 2016 BACKELITE
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@250)]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)
LE LANGUAGE DU FORMAT VISUEL
69
70. 13 MAI 2016 BACKELITE
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@ )]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)
LE LANGUAGE DU FORMAT VISUEL
70
71. 13 MAI 2016 BACKELITE
NSLayoutConstraint.constraintsWithVisualFormat(
"[cancelButton(72@p)]—(spacing)-[acceptButton(>=50)]",
options: [], metrics: metricsDictionary, views: viewsDictionary)
LE LANGUAGE DU FORMAT VISUEL
71
let metricsDictionary = ["spacing": 12,
"p": 250]
72. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
72
[cancelButton]-[acceptButton]
73. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
73
[cancelButton]-[acceptButton ]
74. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
74
[cancelButton]-[acceptButton(==cancelButton)]
75. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
75
|[cancelButton]-[acceptButton(==cancelButton)]|
76. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
76
| [cancelButton]-[acceptButton(==cancelButton)] |
77. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
77
|-[cancelButton]-[acceptButton(==cancelButton)]-|
78. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
78
|- -[cancelButton]-[acceptButton(==cancelButton)]- -|
79. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
79
|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|
80. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
80
H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|
81. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
81
H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|
82. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
82
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: [], metrics: metricsDictionary, views: viewsDictionary)
83. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
83
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: options, metrics: metricsDictionary, views: viewsDictionary)
let options: NSLayoutFormatOptions = .AlignAllTop
84. 13 MAI 2016 BACKELITE
LE LANGUAGE DU FORMAT VISUEL
84
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|-5-[cancelButton]-[acceptButton(==cancelButton)]-5-|",
options: options, metrics: metricsDictionary, views: viewsDictionary)
let options: NSLayoutFormatOptions = .AlignAllCenterX
85. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
• Méthodes sur UIView
85
// ajout
public func addConstraint(constraint: NSLayoutConstraint)
public func addConstraints(constraints: [NSLayoutConstraint])
// suppression
public func removeConstraint(constraint: NSLayoutConstraint)
public func removeConstraints(constraints: [NSLayoutConstraint])
86. 13 MAI 2016 BACKELITE
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 !
86
v1.translatesAutoresizingMaskIntoConstraints = false
87. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
87
Sur quelle vue ajouter les
contraintes ?
88. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
88
Sur quelle vue ajouter les
contraintes ?
89. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
89
Sur quelle vue ajouter les
contraintes ?
90. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
90
Sur quelle vue ajouter les
contraintes ?
91. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
91
Sur quelle vue ajouter les
contraintes ?
92. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
92
Sur quelle vue ajouter les
contraintes ?
93. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
93
Sur quelle vue ajouter les
contraintes ?
94. 13 MAI 2016 BACKELITE
AJOUT DE CONTRAINTES
94
Sur quelle vue ajouter les
contraintes ?
95. 13 MAI 2016 BACKELITE
ACTIVATION / DÉSACTIVATION DE CONTRAINTES
• Méthodes sur NSLayoutConstraint
95
// activation - désactivation
+ (void)activateConstraints:(NSArray *)constraint;
+ (void)deactivateConstraints:(NSArray *)constraint;
96. 13 MAI 2016 BACKELITE
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
96
97. 13 MAI 2016 BACKELITE
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
97
98. 13 MAI 2016 BACKELITE
AUTO LAYOUT ET SCROLLVIEW
98
UIScrollview
ContentView
View View
View
View
99. 13 MAI 2016 BACKELITE
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()
}
99
101. 13 MAI 2016 BACKELITE
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.
101
102. 13 MAI 2016 BACKELITE
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.
102
103. 13 MAI 2016 BACKELITE
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.
103
104. 13 MAI 2016 BACKELITE
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.
104
105. 13 MAI 2016 BACKELITE
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.
105
106. 13 MAI 2016 BACKELITE
COMPRENDRE LES LOGS DE LA CONSOLE
Ajout d’identifiants sur les contraintes
Ajout d’identifiants d’accessibilité sur les vues
Désactiver le translateAutoresizingMaskIntoConstraints
106
labelToTop.identifier = "labelToTop"
titleLabel.accessibilityIdentifier = "titleLabel"
sendButton.translatesAutoresizingMaskIntoConstraints = false
107. 13 MAI 2016 BACKELITE
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
107
108. 13 MAI 2016 BACKELITE
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
108
109. 13 MAI 2016 BACKELITE
DÉSACTIVER LE SCROLL VERTICAL D’UNE SCROLLVIEW
109
UIScrollview
ContentView
View View
View
View
0
0
=
=
110. 13 MAI 2016 BACKELITE
DÉSACTIVER LE SCROLL HORIZONTAL D’UNE SCROLLVIEW
110
UIScrollview
ContentView
View View
View
View
0 0
=
=
111. 13 MAI 2016 BACKELITE
VUE FLOTTANTE DANS UNE SCROLLVIEW
111
UIScrollview Container
UIScrollview
ContentView
View View
View
View
View
flottante
0
0
0
0
112. 13 MAI 2016 BACKELITE
LE SPLIT VIEW
112
Split View
Master View Detail View
00
0 0
0
0
0
= 1/3 = x 3
113. 13 MAI 2016 BACKELITE
LE SPLIT VIEW
113
Split View
Master View Detail View
0
0
0
0
0
= 1/3 = x 3
114. 13 MAI 2016 BACKELITE
RÉPARTITION DE VUES DE MÊME TAILLE SUR UN AXE
114
Superview
Vue 1 Vue 2 Vue 3 Vue 4
= =
=
=
= =
115. 13 MAI 2016 BACKELITE
RÉPARTITION DE VUES DE MÊME TAILLE SUR UN AXE
115
Superview
=
Vue 1 Vue 2 Vue 3 Vue 4
= =
= =
=
116. 13 MAI 2016 BACKELITE
RÉPARTITION DE VUES AVEC ESPACEMENT DE MÊME TAILLE SUR UN AXE
116
Superview
Vue 1 Vue 2 Vue 3
= =
=
= =
=
117. 13 MAI 2016 BACKELITE
CENTRER UN GROUPE DE VUES
117
Superview
Conteneur
Vue
Vue
Vue
Vue
0
0
0
0
118. 13 MAI 2016 BACKELITE
UILAYOUTGUIDE
• Définie un rectangle qui peut interagir avec le moteur d’agencement.
• Remplace les dummy views
118
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
119. 13 MAI 2016 BACKELITE
UILAYOUTGUIDE
• Définie un rectangle qui peut interagir avec le moteur d’agencement.
• Remplace les dummy views
119
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)
120. 13 MAI 2016 BACKELITE
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
120
121. 13 MAI 2016 BACKELITE
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
121
122. 13 MAI 2016 BACKELITE
READABLE CONTENT GUIDE
• Définie la largeur maximal pour le texte
• Dépends de la taille du type dynamique
• Reste toujours entre les margins
122
123. 13 MAI 2016 BACKELITE
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
123
125. 13 MAI 2016 BACKELITE
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
125
126. 13 MAI 2016 BACKELITE
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
126
127. 13 MAI 2016 BACKELITE
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
127
128. 13 MAI 2016 BACKELITE
QUELQUES LIENS
128
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
Layout
https://developer.apple.com/library/watchos/documentation/UserExperience/
Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html#//
apple_ref/doc/uid/TP40010853-CH5-SW7
Mysteries of Auto
Layout, Part 1
https://developer.apple.com/videos/play/wwdc2015/218/
Mysteries of Auto
Layout, Part 2
https://developer.apple.com/videos/play/wwdc2015/219/