Conserver des données après le dismiss d'un Popover

#1

Hey bonjour à tous !

J’aurais une petite question qui pourrais m’aider à avancer dans ma petite application!

Je débute donc je n’ai pas encore beaucoup de connaissances en ce qui concerne les delegates et protocols, et pourtant j’ai l’impression que c’est de ce côté-là que ca se passe…

Voilà la problématique : j’ai besoin que mon ViewController change en fonction des choix effectués dans mon PopOverViewController.
Pour faire simple, le “Player1” choisi ses “pouvoirs”, et son “drapeau” dans le PopOver, et de même pour le “Player2”.

Après pas mal de galère (et après avoir suivi le cours sur les segues), j’étais enfin arrivé a faire passer des données (nombres de questions posées, nombres de bonne réponses, etc … ) d’un ViewController a un autre dans une précédente application.

Le soucis c’est que cette segue ne vas que d’un un sens … J’ai donc essayer de faire des IBAction dans l’autre sens, mais là, surprise, on perd l’effet du PopOver qui se dismiss normalement et on reviens a une transition normale…

Après des heures de recherches sur overstack, j’ai l’impression qu’il faudrais créer un protocol dans mon PopOverViewController et appeler ce dernier dans mon ViewController mais je n’arrive vraiment pas à mettre ca en place … Et j’ai aussi l’impression qu’il est possible de le faire de façon beaucoup plus simple.
J’en appelle donc à vous!

Je serais tous a fait d’accord si vous pensez que c’est quelque chose de trop dure à réaliser pour mon niveau. Mais je serais heureux qu’on me mette au moins sur la bonne piste.

Bonne journée a vous !

#2

Hello @Nicow

Tu peux en effet utiliser un protocole pour faire communiquer ton PopOverViewController avec ton ViewController. Après, tu pourrais aussi (je pense), passer une référence de ton ViewController à ton PopOverViewController, ce qui permettrait de “remplir” celui-ci depuis ton PopOverViewController.

Par rapport au delegate, voici ce que tu peux faire:

Dans ton ViewController, tu crées un protocole (appelons le ViewController Delegate):

protocol ViewControllerDelegate {
    func getData(name: String)
} 

Dans ce protocole, tu peux mettre les fonctions que tu souhaites, par exemple, ici, j’ai uniquement mis une fonction getData qui reçoit un nom, mais tu peux aussi passer autre chose par cette fonction si tu veux.

Une fois que le protocole est créé, tu l’implémentes sur ton ViewController, comme ceci:

class ViewController: UIViewController, ViewControllerDelegate

En faisant ça, tu vas devoir implémenter les méthodes de ton protocol, ce qui donnera:

func getData(name: String) {
    // ta logique, par exemple, tu peux créer une variable name dans ton ViewController, comme ceci: var name: String?
    // et ensuite, faire ceci: self.name = name
}

Dernière chose à faire dans le ViewController, dans la fonction:

prepare(for segue: UIStoryboardSegue)

tu peux faire quelque chose comme ceci:

if segue.identifier == "mySegue" {
    if let destination = segue.destination as? PopOverViewController {
        destination.viewControllerDelegate = self // viewControllerDelegate est une variable que l'on va définir dans le PopOverViewController
    }
}

Tu vérifies le segue que tu vas pusher (avec son identifier), ensuite, tu vérifies que la destination de ce segue est bien de type PopOverViewController, et si tel est le cas, tu définis le delegate de ta destination comme étant ce controller-ci.

En faisant ça, tu dis que ton PopOverViewController aura une référence vers les fonctions du protocole de ton ViewController, et donc, depuis ton PopOverViewController, tu pourras appeler la fonction “getData” par exemple.

Enfin, dernière chose à faire, dans ton PopOverViewController:
Tu définis une variable qui correspond au delegate:

var viewControllerDelegate: ViewControllerDelegate?

et ensuite, tu peux utiliser les fonctions de ce delegate pour faire passer des informations depuis ton PopOverViewController vers ton ViewController en faisant ceci:

viewControllerDelegate?.getData(name: "mon super nom")

Par exemple, si tu fais un bouton qui ferme ton PopOverViewController, comme ceci:

@IBAction func dismissAction(_ sender: UIButton) {
    viewControllerDelegate?.getData(name: "mon super nom")
    self.dismiss(animated: true, completion: nil)
}

Une fois de retour dans ton ViewController, tu auras effectué la méthode “getData”, donc, tu auras accès aux informations que tu as passé via le protocole depuis ton PopOverViewController.

Le concept n’est pas le plus simple à comprendre au début (je trouve), mais une fois compris, il est assez pratique! :slight_smile:

Voici le code en entier, pour te permettre d’avoir une vue d’ensemble sur ce que j’ai expliqué plus haut:

Le storyboard:

Le ViewController et le protocole:

Le PopOverViewController:

Si tu as des questions, n’hésite pas à les poser, nous sommes là pour y répondre et t’aider au besoin.

En espérant t’avoir aidé,

Bonne journée,

Alexandre

#3

Salut Alexandre !

Merci de ta réponse !

Du coup, je vais voir tous ça ce soir mais j’aurais une dernière petite chose à préciser : mon PopUpViewController est de type “PopOverViewControllerDelegate”. Ce qui ressemble a ça :

En vous remerciant :slight_smile:

#4

Qu’entends-tu par

est de type “PopOverViewControllerDelegate”

?

Ta classe hérite t’elle d’un ViewController ? Ou d’une vue ? Ou d’autre chose ? :slight_smile:

#5

Mon premier storyboard a une classe ViewController et une classe UIPopoverPresentationControllerDelegate. Mon second storyboard (qui est le PopOver) as une classe ViewController seulement (Comme les 5 autres ViewController)

Voici mon segue pour faire apparaitre Mon Second Storyboard (et les 5 autres)

if segue.identifier == "sg_perso1" {
            let popopoverViewController = segue.destination
            popopoverViewController.modalPresentationStyle = .popover
            popopoverViewController.presentationController?.delegate = self
            popopoverViewController.popoverPresentationController?.sourceView = buttonChoixPerso1
            popopoverViewController.popoverPresentationController?.sourceRect  = CGRect(x: 0, y: 0, width: buttonChoixPerso1.frame.size.width, height: buttonChoixPerso1.frame.size.height)
            
        }

J’ai choisi un UIPopoverPresentationControllerDelegate parce que j’adore le faite de pouvoir faire disparaître le PopOver en cliquant n’importe où sur l’ecran.

Je ne sais pas si ça répond à ta questions mais voilà!

#6

Hello,

Essaye de mettre en pratique ce que je t’ai dis plus haut, ça devrait fonctionner je pense :slight_smile:

Si pas, envoi nous ton code, que l’on puisse y jeter un oeil.

Bonne journée,

Alexandre

#7

Salut!

Merci pour la réponse, ça marche à la perfection. :pray:

A pluche !