web-dev-qa-db-fra.com

Comment transmettre des données à un autre contrôleur lors de la fermeture de ViewController?

Je souhaite transmettre mes données d'une ViewController à un autre VC sur VC. C'est possible?

J'ai essayé la méthode suivante et sans succès:

Sur le bouton clic:

self.dismiss(animated: true) { 
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "EditViewController") as! EditViewController
        controller.segueArray = [values]
    }

lorsque EditViewController apparaît à nouveau, ma segueArray est nil ici.

Comment puis-je transmettre mes données de my ViewController à la EditViewController lors du renvoi?

8
John Doe

Le meilleur moyen de transmettre des données au contrôleur de vue précédent consiste à utiliser des délégués ... lorsque vous passez de ViewController A à B, transmettez le contrôleur de vue A en tant que délégué et sur la méthode viewWillDisappear de ViewController B, appelez la méthode déléguée dans ViewController A. Les protocoles aideraient à définir le délégué et les méthodes requises pour être implémentées par les VC précédents. Voici un exemple rapide:

Protocole de transmission de données:

protocol isAbleToReceiveData {
  func pass(data: String)  //data: string is an example parameter
} 

Contrôleur de vue A:

class viewControllerA: UIViewController, isAbleToReceiveData {

  func pass(data: String) { //conforms to protocol
  // implement your own implementation
   }

  prepare(for: Segue) {
    /** code for passing data **/
    let vc2 = ViewCOntrollerB()  /
    vc2.delegate = self   //sets the delegate in the new viewcontroller 
                          //before displaying
    present(vc2)
  }
}

Rejeter viewcontroller:

class viewControllerB: UIViewController {

  var delegate: isAbleToReceiveData

  viewWillDisappear {
      delegate.pass(data: "someData") //call the func in the previous vc
  }
}
9
the_legend_27

Dans le bloc d'achèvement, vous créez une nouvelle instance de EditViewController. Je suppose qu'une autre instance EditViewController existe déjà dans la pile de navigation, vous devez donc trouver cette instance et définir le segueArray sur les valeurs ..__ que vous pouvez obtenir en effectuant une itération dans les contrôleurs de vue de votre pile de navigation, comme:

viewController.navigationController?.viewControllers.forEach({ (vc) in
    if let editVC = vc as? EditViewController {
        editVC.segueArray = ....
    }
})

Mais je recommanderais d'utiliser le modèle de délégué, comme:

protocol EditViewControllerDelegate: class {
    func setSegueArray(segues: [UIStoryboardSegue])
}

Dans le viewcontroller (appelez-le juste ViewController) où se trouve le bloc de renvoi, déclarez une propriété de délégué:

class ViewController: UIViewController {
    weak var delegate: EditViewControllerDelegate?
    ....
}

Ensuite, lors de la présentation de l'instance de (je suppose d'EditViewController), ViewController a défini le délégué comme suit:

...
if let vc = presentingViewController as? ViewController {
    vc.delegate = self
}

Et conformez EditViewController au protocole de délégué comme suit:

extension EditViewController: EditViewControllerDelegate {
    func setSegueArray(segues: [UIStoryboardSegue]) {
        // Do the data setting here eg. self.segues = segues
    }
}
1
Bence Pattogato

Pour détecter quand le bouton de retour est enfoncé sur un contrôleur de vue, j'utilise simplement:

override func didMove(toParentViewController parent: UIViewController?) {
    guard parent == nil else { return } // Back button pressed

    ... // Pass on the info as shown in you example
} // didMoveToParentViewController
0
KerCodex