15

A couple of weeks ago I asked this question and got a very detailed explanation. Now I would like to pass data back to the first ViewController but I keep getting stuck using the same method. I have a modal of the first VC to the second, where I would like to edit an array of strings, which will be showed on the first view again. So on my first view I have an array of data, which should be passed to the second so edit fields show the current information after which the user has to be able to edit the contents of the array and pass that data back to the first where it is shown on labels. I'm using Swift.

My code:

(in ViewController.swift:)

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
        let secondVC = segue.destinationViewController as SecondViewController
        secondVC.namesPlayers = self.namesPlayers
    }

(in SecondViewController.swift:)

override func viewDidLoad() {
    super.viewDidLoad()
    labelFirstPlayer.text = namenSpelers[0]
}

Thank you

Community
  • 1
  • 1
B_s
  • 2,771
  • 5
  • 25
  • 50

3 Answers3

37

You need to use a delegate. Here is an example how do use a delegate in Swift.

On your first ViewController, set your delegate when you load the second VC:

For example, if you are using the Storyboard Editor:

var secondViewController = (segue.destinationViewController.visibleViewController as  MySecondViewControllerClass)
secondViewController.delegate = self

Write a Protocol and define a func to write you values back

For example, create a file called "Protocol.swift" and write something like that:

protocol writeValueBackDelegate {
    func writeValueBack(value: String)
}

Add the function to your FirstViewController

func writeValueBack(value: String) {
   // Or any other function you need to transport data
}

And to your ViewControllerClass

class ViewController: UIViewController, writeValueBackDelegate

The above line will not work if you have not implemented all of the methods in ViewController that you defined in your protocol file.

Go to the Second View Controller, and add the delegate here:

class SecondViewController: ViewController {

    // Delegate for FirstViewController
    // Declare as weak to avoid memory cycles
    weak var delegate: writeValueBackDelegate?
}

On your Second View Controller, you can now use this to call the func in the first View Controller an pass data.

delegate?.writeValueBack("That is a value")
Bernardo Santana
  • 454
  • 5
  • 18
derdida
  • 14,120
  • 15
  • 78
  • 131
  • You also need to indicate that your first view controller implements the protocol: `class ViewController: UIViewController, writeValueBackDelegate {` – vacawama Aug 27 '14 at 09:51
  • Can't we use closures here to achieve the same? – Satyam May 24 '15 at 14:44
  • @derdida Can I to make a reverse way that I manage data from FirstViewController into SecondViewController? Thanks – Alexander Khitev Aug 11 '15 at 14:07
  • For sure: Check out my answer here: https://stackoverflow.com/questions/26089152/sending-data-with-segue-with-swift/26089243#26089243 – derdida Aug 11 '15 at 14:08
  • Should `var secondViewController = (segue.destinationViewController.visibleViewController as MySecondViewControllerClass) secondViewController.delegate = self ` be put in the prepare for segue method? – Cesare Dec 09 '16 at 20:42
0

I'm confused by the answer using delegates, because it seems to me needlessly complicated. Here's what I did to pop-up an Add Player dialog in my card game, and pass the results back to the calling view controller.

Add delegate protocol (in my case in my Extensions/Protocols file)

protocol ReturnPlayerInfoDelegate {
   func returnPlayerInfo(playerName : String, playerType : Player.Type)
}

Then I added my reference (as a class var) to the delegate in the CALLED View Controller. Note this didn't require my subclassing my caller, or adding the protocol to my called View Controller:

class AddPlayerViewController : UIViewController {
     static var delegate : ReturnPlayerInfoDelegate!

and called the delegate in my Ok button handler:

    @IBAction func onOK(sender: UIButton) {
      AddPlayerViewController.delegate.returnPlayerInfo(mPlayerName.text!, playerType: mPlayerTypeActual)
    dismissViewControllerAnimated(true, completion: nil)
}

Now I implemented the delegate in the CALLING ViewController:

class FiveKings : UIViewController, UIGestureRecognizerDelegate, UIPopoverPresentationControllerDelegate ,UITextViewDelegate , ReturnPlayerInfoDelegate {
...
    override func viewDidLoad() {
         super.viewDidLoad()

         AddPlayerViewController.delegate = self
...
    func returnPlayerInfo(playerName : String, playerType : Player.Type) {
        mGame.addPlayer(playerName, newPlayerClass: playerType, fKActivity: self)
}

This works very nicely. Do you see any problems with my implementation?

Opus1217
  • 593
  • 3
  • 14
  • You said you were confused by the answer using delegates. And you also use delegate in your answer. What did you mean you were confused? – Joe Huang Feb 16 '17 at 14:42
  • You also need to make sure that your delegate variable is weak to prevent a memory cycle `static weak var delegate : ReturnPlayerInfoDelegate?` – pho_pho Sep 06 '17 at 09:01
0

Hope this will help you

This the second controller from where you want to return data to pushed. SecondView.swift

@objc protocol returnDataProtocol {
    func returnStringData(myData: String)
 }




 class SecondView: UIViewController {


        weak var delegate: returnStringData?


        @IBAction func readyButtonPressed(sender: AnyObject) {

        // Do what you want here 

        delegate?.returnStringData("Euro/Dollar etc....")
         // this function is exist in first view controller 

        }
    }

First view ViewController firstView.swift

class firstView: UIViewController, returnDataProtocol {
    // this function will call to second view. You can use here push method, if you are using navigation controller. 
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "mySegue" { // your identifier here
            let controller = segue.destinationViewController as! MyPopOverController
            controller.delegate = self
        }
    }

   // here you will get return value from second view controller class

    func returnStringData(myData: String){
          print(myData)
       }

}
RviOS
  • 23
  • 4