Nous avons maintenant une belle classe Game
qui va gérer toute la logique de notre jeu. Notre contrôleur va pouvoir utiliser les deux méthodes publiques que nous avons définies :
answerQuestion
: quand l'utilisateur répond à une question.refresh
: quand l'utilisateur appuie sur le bouton New Game.
Dans le premier cas, notre modèle renvoie le score mis à jour à partir de la réponse à la question. Mais dans le deuxième cas, on doit attendre le chargement des questions. Alors comment le modèle va-t-il pouvoir prévenir le contrôleur que les questions sont chargées et que la partie peut débuter ? C'est ce que nous allons voir dans ce chapitre !
Les notifications dans le MVC
Nous avons vu dans le chapitre sur le MVC que le modèle ne pouvait pas s'adresser directement au contrôleur. Il ne doit même pas savoir que le contrôleur existe.
Seulement, nous avons besoin ici de lui dire que les questions ont été chargées pour qu'il puisse lancer la nouvelle partie à l'écran. Et pour cela nous allons utiliser une technique de communication aveugle : les notifications.
Les notifications fonctionnent comme une radio. N'importe quel objet peut décider de devenir émetteur et n'importe qui peut décider de devenir récepteur. Comme à la radio, un animateur ne peut pas savoir qui sont les personnes qui suivent son émission. Et de la même façon, les recepteurs ne savent pas où se trouve l'émetteur et qui il est. C'est la raison pour laquelle on appelle cela une technique de communication aveugle. On ne sait pas qui parle et qui écoute.
Dans notre cas, c'est donc le modèle qui va émettre pour déclarer : "Les questions sont chargées" et le contrôleur qui va écouter. Comme la communication est aveugle, le modèle peut s'adresser au contrôleur sans même savoir que le contrôleur existe.
Implémenter les notifications
Nous allons donc envoyer notre notification dans la méthode refresh
une fois que les questions sont chargées. Pour envoyer une notification en iOS, il faut utiliser trois types du framework Foundation : Notification.Name
, Notification
et NotificationCenter
. Si Notification
est une emission de radio, Notification.Name
c'est son nom ou sa fréquence et NotificationCenter
c'est le poste de radio. C'est le NotificationCenter
qui a le rôle d'envoyer et de recevoir des notifications.
Commençons par créer le nom de notre notification. Tous ceux qui veulent écouter ma radio devront utiliser le même nom :
let name = Notification.Name(rawValue: "QuestionsLoaded")
Notification.Name
est une structure. On utilise son initialisation avec le paramètre rawValue
.
class Notification {
struct Name {
}
}
Ensuite nous allons créer la notification en lui passant la variable name
lors de son initialisation.
let notification = Notification(name: name)
Il ne nous reste plus qu'à envoyer la notification avec le NotificationCenter
:
NotificationCenter.default.post(notification)
Le NotificationCenter
c'est le poste de gestion des notifications. Le poste principale s'appelle default
.
On utilise ensuite la méthode post
qui prend en paramètre la notification que nous venons de créer. À la fin, notre méthode refresh ressemble à ceci :
func refresh() {
score = 0
currentIndex = 0
state = .over
QuestionManager.shared.get { (questions) in
self.questions = questions
self.state = .ongoing
let name = Notification.Name(rawValue: "QuestionsLoaded")
let notification = Notification(name: name)
NotificationCenter.default.post(notification)
}
}
Et voilà la notification est partie !
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "QuestionsReceived"), object: nil)
Le paramètre object
permet d'envoyer des données avec la notification.
Il nous reste à mettre en place le récepteur côté contrôleur. Et nous ferons cela dans la dernière partie de ce cours dédiée au contrôleur !
En résumé
Le modèle ne peut pas communiquer directement avec le contrôleur puisqu'il ne doit même pas savoir qu'il existe. Lorsqu'on a vraiment besoin que le modèle envoie une information au contrôleur, on utilise une notification.
Les notifications forment un mode de communication aveugle, car l'émetteur ne connaît pas le récepteur et inversement.
Les notifications doivent avoir un nom. Ce nom permet de l'identifier et permet du coup aux récepteurs d'écouter la communication.
On envoie une notification comme ceci :
let name = Notification.Name(rawValue: "LeNomDeMaNotification")
let notification = Notification(name: name)
NotificationCenter.default.post(notification)