Dans le chapitre précédent, nous avons créé un objet Pet avec les informations rentrées par l'utilisateur dans le formulaire. Dans un véritable projet, on utiliserait sans doute ces données pour les envoyer sur un serveur et inscrire effectivement notre chien dans une base de données.
Mais ce n'est pas l'objet de ce cours, et nous allons essayer de faire quelque chose d'un peu plus simple. Nous allons passer les données à la page suivante ( SuccessViewController
) pour personnaliser le message avec le nom du chien qui vient de s'inscrire.
La transmission de données entre contrôleurs
De manière générale, il y a trois façons de passer des données entre contrôleurs :
1/ Les données sont stockées par un tiers
Si les données sont stockées par un tiers, les contrôleurs n'ont qu'à venir piocher dedans les uns après les autres. Le tiers fait office de base de données pour tout le monde.
C'est quoi le tiers ?
Le tiers peut représenter différentes choses :
Un serveur dans le cloud qui détient les données.
Le modèle qui retient les données via des mécanismes, comme le singleton pattern dont on parlera dans un prochain cours.
Une base de données en local, c'est-à-dire dans votre application iPhone. Vous avez par exemple
Core Data
, dont nous parlerons dans un prochain cours.
2/ Les données sont synchronisées directement entre les contrôleurs
Via un système de notifications, un contrôleur peut notifier un ou plusieurs autres contrôleurs qu'une donnée vient d'être mise à jour. Les autres contrôleurs peuvent réagir à la nouvelle, et adapter leur interface en conséquence.
3/ Les données sont transmises lors de la transition entre deux contrôleurs
Lorsque l'on passe d'un contrôleur à un autre, via un segue par exemple, on peut associer à cette transition une transmission de données.
L'idée générale, c'est :
Le premier contrôleur détient des données.
Avant que la transition n'ait lieu, il récupère une référence au contrôleur suivant, via laquelle il peut lui transmettre les données.
Recréez la transition
Au chapitre précédent, nous avons supprimé le segue modal entre le FormViewController
et le SuccessViewController.
La raison, c'est que nous voulons effectuer certaines actions, comme créer un objet Pet
et ensuite le transmettre à SuccessViewController
, avant que la transition n'ait lieu.
Il ne faut donc pas que la transition ait lieu automatiquement lorsqu'on appuie sur le bouton Valider. Pour cela, nous n'allons pas associer la transition au bouton comme on a appris à le faire jusqu'à présent, mais au contrôleur directement.
Pour faire cela, il vous suffit de recréer un segue Present Modally
, mais qui part cette fois du contrôleur FormViewController
, et qui atterrit toujours sur SuccessViewController
.
Maintenant, sélectionnez le segue nouvellement créé et ouvrez l'inspecteur d'attributs :
La propriété Identifier
va nous permettre de nommer ce segue. Nous allons utiliser ce nom pour faire référence à ce segue quand on voudra l'utiliser côté code.
Vous pouvez écrire par exemple : segueToSuccess
.
Préparez la transition
Notre segue est prêt et identifiable. Nous allons pouvoir l'utiliser dans le code pour lancer notre transition. Mais juste avant cela, il nous faut passer les données d'un contrôleur à l'autre.
Pour cela, nous allons utiliser une méthode que vous avez peut-être déjà vue, car elle est par défaut dans le code d'un ViewController :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
La méthode prepareForSegue
est exécutée juste avant que la transition n'ait lieu. Elle prend en paramètre le segue responsable de la transition de type UIStoryboardSegue
et un sender
– c'est l'objet d'où part le segue.
Dans le cas où le segue est initié par un bouton, l’objet sender sera ce même bouton. Cependant, dans le cas où le segue est associé à un contrôleur, nous allons voir que c’est à nous de définir le sender.
Vous implémenterez presque toujours cette méthode de la même façon :
On vérifie que l'identifiant du segue est le bon.
On récupère le contrôleur à destination du segue.
On passe les données au contrôleur de destination.
C'est parti !
1/ Vérification de l'identifiant
La classe UIStoryboardSegue
a une propriété identifier de type String?
qui contient l'identifiant. Donc pour vérifier que l'identifiant est bon, nous allons simplement faire :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToSuccess" {
}
}
2/ Récupération du contrôleur de destination
Nous allons maintenant récupérer une référence du contrôleur vers lequel nous allons. Et pour cela, nous allons utiliser une autre propriété de UIStoryboardSegue
: destination
.
Et nous allons du coup écrire ceci :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToSuccess" {
let successVC = segue.destination as? SuccessViewController
}
}
On crée une constante à partir de la propriété destination
du paramètre segue
. Et ensuite, on vérifie avec le contrôle de type ( as?
) que le contrôleur de destination est bien du type SuccessViewController
.
3/ Passage des données
La donnée que l'on souhaite transmettre, c'est l'objet dog
que nous avons créé dans la méthode createPetObject
:
let dog = Pet(name: name, hasMajority: hasMajority, phone: phone, race: race, gender: gender)
Il faut commencer par récupérer cette donnée dans la méthode prepareForSegue
. Et pour partager les données entre méthodes, nous avons deux solutions : soit on crée une propriété dans le contrôleur, soit on utilise le fameux objet sender
.
Tout d’abord, nous allons demander à la méthode createPetObject
de retourner le Pet
créé :
private func createPetObject() -> Pet {
let name = nameTextField.text
let phone = phoneTextField.text
let hasMajority = majoritySwitch.isOn
let gender = genderSegmentedControl.selectedSegmentIndex == 0 ? Pet.Gender.male : Pet.Gender.female
let race = dogRaces[racePickerView.selectedRow(inComponent: 0)]
return Pet(name: name, hasMajority: hasMajority, phone: phone, race: race, gender: gender)
}
La méthode validate
va dorénavant recevoir un objet Pet
, qu’elle pourra communiquer en tant que sender
lorsqu’elle va initier la transition.
Lancer la transition
Pour lancer un segue programmatiquement, il suffit d'utiliser la méthode suivante :
performSegue(withIdentifier: String, sender: Any?)
Cette méthode de ViewController
prend en paramètre l'identifiant du segue à lancer et l'objet qui est normalement à l'origine du segue. En pratique, on mettra souvent self
puisque c'est le contrôleur qui initie la transition. Mais comme indiqué précédemment, nous pouvons aussi exploiter cette propriété pour faire passer des informations.
Je vous suggère donc d'écrire dans l'action validate :
@IBAction func validate() {
let pet = createPetObject()
performSegue(withIdentifier: "segueToSuccess", sender: pet)
}
Il ne reste plus qu'à récupérer l’objet Pet et à le transmettre au contrôleur de destination. Nous allons donc récupérer l’objet via la propriété sender, et l'attribuer à une propriété Pet
que vous allez devoir ajouter au contrôleur SuccessViewController
.
class SuccessViewController: UIViewController {
var dog: Pet?
// (...)
}
Puis la transmision dans le prepareForSegue
:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToSuccess" {
let successVC = segue.destination as? SuccessViewController
let pet = sender as? Pet
successVC?.dog = pet
}
}
Et voilà ! Vous pouvez vérifier que la transition modale a de nouveau lieu lorsqu'on appuie sur le bouton Valider. La différence, c'est que maintenant on récupère les informations du formulaire, on les passe au contrôleur suivant et ensuite on lance la transition.
Vous pouvez le vérifier en ajoutant un print dans le viewDidLoad
de la classe SuccessViewController
.
Exercice
À vous de jouer ! La donnée a atterri dans le SuccessViewController
. Il faut maintenant l'utiliser pour afficher le nom du chien dans le message affiché à l'écran.
Le message que vous devez afficher dans le label est le suivant :
Wouf de bienvenue à [NOM DU CHIEN] !
Vous avez bien été ajouté à notre base de données ! Nous vous enverrons un SMS dès que nous aurons une âme sœur à vous proposer !
Pour y parvenir, vous allez devoir :
créer un outlet pour modifier le texte du label ;
créer le texte ci-dessus en incluant le nom du chien, récupéré dans la propriété
dog
;modifier le texte au chargement de la vue.
Bonne chance !
En résumé
Il existe trois façons de faire passer des données entre contrôleurs :
Les données sont stockées par un tiers.
Les données sont synchronisées directement entre les contrôleurs.
Les données sont transmises lors de la transition entre deux contrôleurs.
Pour cette troisième façon, on suit les étapes suivantes :
On crée un segue entre les contrôleurs, et on lui donne un identifiant.
Dans la méthode
prepareForSegue
, on récupère une référence au contrôleur de destination et on lui passe les données.On lance la transition avec la méthode
performSegue
.
Dans le prochain chapitre, nous allons ajouter une étape à notre formulaire : sa vérification.