• 8 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 5/26/23

Passez des données entre contrôleurs

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  .

Une flèche part de la page d'inscription au SuccessViewControler

Maintenant, sélectionnez le segue nouvellement créé et ouvrez l'inspecteur d'attributs :

Inspecteur d'attributs : Storyboard Segue

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 :

  1. On vérifie que l'identifiant du segue est le bon.

  2. On récupère le contrôleur à destination du segue.

  3. 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 :

    1. Les données sont stockées par un tiers.

    2. Les données sont synchronisées directement entre les contrôleurs.

    3. Les données sont transmises lors de la transition entre deux contrôleurs.

  • Pour cette troisième façon, on suit les étapes suivantes :

    1. On crée un segue entre les contrôleurs, et on lui donne un identifiant.

    2. 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.

    3. On lance la transition avec la méthode  performSegue  .

Dans le prochain chapitre, nous allons ajouter une étape à notre formulaire : sa vérification.

Example of certificate of achievement
Example of certificate of achievement