Nous avons maintenant une belle interface ! Et avant de passer à la suite, nous allons la rendre pratique à utiliser ! Dans ce chapitre, nous allons apprendre à créer notre propre vue customisée.
Pourquoi faire une vue customisée ?
Si on regarde notre vue question, elle est assez compliquée. Non seulement c'est une vue qui en contient deux autres : le label et l'icône. Mais en plus, si on se fie à l'image ci-dessous, cette vue va s'afficher de trois façons différentes :
L'utilisateur répond faux à la question : le fond devient rouge et la croix rouge apparait
L'utilisateur répond vrai à la question : le fond devient vert et le symbole validé apparaît
L'utilisateur n'a pas encore répondu à la question : le fond est gris et le symbole est caché
Donc pour que cette vue soit plus simple à gérer pour notre contrôleur tout à l'heure, nous allons créer une vue customisée. Et pour créer une vue customisée avec iOS, on crée une sous-classe de UIView
. Vous risquez d'avoir souvent besoin de faire cela donc c'est le bon moment pour le découvrir ! Vous êtes partant ?
Parfait ! Bravo pour votre enthousiasme !
Créons la sous-classe
Nous allons créer une classe QuestionView
qui va hériter de UIView
. Pour cela, il faut créer un nouveau fichier.
Mais cette fois-ci, vous allez choisir la première option Cocoa Touch Class :
Cliquez sur Next. Cette option nous permet de créer un fichier qui est directement une sous-classe de la classe que l'on souhaite. Cela permet de gagner un peu de temps. Dans le champ Subclass of, vous allez donc choisir UIView
. Et au-dessus, vous allez nommer votre classe QuestionView
.
Cliquez sur Next et sauvegardez votre fichier en choisissant le groupe View
puisque nous travaillons toujours dans la partie vue du MVC. Vous avez maintenant un fichier QuestionView.swift
qui contient le code suivant :
class QuestionView: UIView {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
Il s'agit bien de la déclaration d'une classe QuestionView
qui hérite de UIView
.
Connecter la classe
Maintenant que notre classe est créée, nous allons la connecter avec notre vue dans le storyboard. Nous allons faire ça en deux étapes :
Nous allons changer la classe de notre vue dans le storyboard
Nous allons connecter le label et l'icône à notre classe
Changer la classe de notre vue
Retournons dans le storyboard. Notre vue grise qui contient les questions est à l'origine une UIView
que nous avons glissée depuis la bibliothèque des composants. Il est temps d'en faire une QuestionView
!
Pour cela, il faut aller dans l'inspecteur d'identité. C'est un des onglets que nous n'avons pas encore vus dans le panneau des utilitaires à droite.
Dans cet onglet, on peut vérifier après avoir sélectionné la vue que la classe actuelle de notre vue est bien UIView
. Pour modifier cela, il suffit d'écrire notre nouvelle classe dans le premier champ de texte comme ceci :
Et voilà notre vue a maintenant pour classe QuestionView
! Cela va nous permettre de connecter le label et l'icône à notre classe.
Connecter le label et l'icône
Notre classe contient deux vues : le label et l'icône. Nous allons en faire des propriétés de notre classe QuestionView
. Vous savez déjà créer des propriétés :
var label: UILabel?
var icon: UIImageView?
On utilise ici les optionnels, car on ne sait pas la valeur de ces deux propriétés.
Notre objectif avec cette classe est de simplifier l'utilisation de la vue. Dans le cadre de cette simplification, les personnes qui utilisent cette classe n'ont pas besoin de savoir son contenu. Donc nous allons marquer ces propriétés privées.
private var label: UILabel?
private var icon: UIImageView?
Maintenant, faisons la connexion ! Une connexion entre une propriété et une vue avec Xcode s'appelle un Outlet.
Donc pour faire la connexion, nous allons rajouter ce qu'on appelle un décorateur :
@IBOutlet private var label: UILabel?
@IBOutlet private var icon: UIImageView?
Le mot-clé @IBOutlet
notifie Xcode que ces propriétés sont susceptibles d'être connectées à une vue dans Interface Builder. En reconnaissant ce mot-clé, Xcode rajoute un petit rond à côté de nos propriétés :
C'est ce petit rond qui va nous permettre de faire la connexion.
Pour cela, nous allons retourner dans le storyboard. Et nous allons nous placer en mode assistant. En mode assistant, pour choisir le fichier à afficher sur la droite, vous pouvez naviguer comme ceci :
Choisissez le fichier QuestionView.swift
. Et nous allons maintenant faire la connexion entre la propriété et la vue correspondante. Pour cela, nous allons glisser depuis le petit rond vers la vue comme ceci :
Et voilà ! Notre classe est maintenant complètement connectée au storyboard. Il ne nous reste qu'une toute petite amélioration.
Le type optionnel déballé
Comme nos propriétés sont connectées à des vues qui existent dans le storyboard, on est certain que ces propriétés n'auront pas pour valeur nil
. Donc au lieu de leur donner un type optionnel, on va leur donner un type optionnel déballé :
@IBOutlet private var label: UILabel!
@IBOutlet private var icon: UIImageView!
En remplaçant, le point d'interrogation par un point d'exclamation, on indique qu'on ne connait pas la valeur de nos optionnels, mais qu'on est certain qu'elle ne vaut pas nil
. À chaque fois que la propriété va être utilisée, l'optionnel va être implicitement déballé.
Le type optionnel déballé nous permet donc de ne pas donner de valeur à notre propriété tout en n'ayant pas à la déballer à chaque fois que l'on souhaite l'utiliser.
En Résumé
Pour faire une vue customisée, on crée une sous-classe de
UIView
.Pour créer une sous-classe de
UIView
, on choisit Cocoa Touch Class dans le menu Nouveau fichier d'Xcode.Une connexion entre une propriété et une vue dans le storyboard s'appelle un
Outlet
. Pour pouvoir créer unOutlet
dans une vue customisée, il faut :Avoir connecté la classe et la vue via l'inspecteur d'identité dans les utilitaires
Créer les propriétés correspondantes aux vues
Ajouter le décorateur
@IBOutlet
.Glisser le petit rond vers la vue.
Le type optionnel déballé permet de déclarer une propriété dont on ne connaît pas la valeur mais dont on est certain qu'elle existe. Cela évite de devoir déballer l'optionnel à chaque fois qu'on souhaite l'utiliser.