0

I am following the accepted answer to this question, but I am having issues passing the data from ViewControllerB (second View Controller) back to ViewController (initial View Controller). Based on the output of a few print statements I added, I think the unwind to ViewController is happening before textFieldDidEndEditing.

dataPassed from ViewControllerB: Default passed data
newValue: Default passed data
textFieldDidEndEditing: Pass this back

I was able successfully pass the data back to ViewController by creating an outlet to the button on ViewControllerB and setting dataPassed = textField.text. Another way I was able to get this to work was by changing dataReceived = sourceViewController.dataPassed to dataReceived = sourceViewController.textField.text in the unwindToThisController function. But it does not look like the poster of the accepted answer mentioned above used either or these workarounds, and I am unsure if either of these workarounds are an acceptable way to do this.

I am using Xcode 8.2.1 and Swift 3.

ViewController code (initial View Controller)

/* ViewController.swift */
import UIKit

class ViewController: UIViewController {

  var dataReceived: String? {
    willSet {
      print("newValue: " + newValue!)
      labelOne.text = newValue
    }
  }

  @IBOutlet weak var labelOne: UILabel!

  @IBAction func buttonOne(_ sender: UIButton) {
    performSegue(withIdentifier: "viewNext", sender: self)
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    labelOne.text = "Default passed data"
  }

  // Segue ViewController -> ViewControllerB
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "viewNext" {
      let viewControllerB = segue.destination as! ViewControllerB
      viewControllerB.dataPassed = labelOne.text
    }
  }

  // Segue ViewController <- ViewControllerB
  @IBAction func unwindToThisControllerWithSegue(sender: UIStoryboardSegue) {
    if let sourceViewController = sender.source as? ViewControllerB {
      print("dataPassed from ViewControllerB: " + sourceViewController.dataPassed!)
      dataReceived = sourceViewController.dataPassed
      //dataReceived = sourceViewController.textField.text
    }
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

}

ViewControllerB code (second View Controller)

/* ViewControllerB.swift */
import UIKit

class ViewControllerB: UIViewController, UITextFieldDelegate {

  var dataPassed: String?

  @IBOutlet weak var textField: UITextField!

  override func viewDidLoad() {
    super.viewDidLoad()
    textField.text = dataPassed
    textField.delegate = self
  }

  // Text field delegate methods
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
  }

  func textFieldDidEndEditing(_ textField: UITextField) {
    print("textFieldDidEndEditing: " + textField.text!)
    dataPassed = textField.text
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

}
Community
  • 1
  • 1
mosley
  • 13
  • 4
  • What happens if you put a breakpoint at `print("dataPassed from ViewControllerB: " + sourceViewController.dataPassed!)`? can you inspect `sourceViewController` and see which properties are being defined? – brandonscript Jan 12 '17 at 18:02
  • For what it's worth, I think you're right — that the IBAction event to dismiss the view controller is happening before `textFieldDidEndEditing` is called. You could just change the order of things and have the done button deal with resigning first responder, and have a different button or function that dismisses the view controller. – brandonscript Jan 12 '17 at 18:05
  • @mosley - Have you tried just saying `dataPassed = sourceViewController.textField.text` inside `unwindToThisControllerWithSegue`? Instead of waiting for the `UITextField` delegate to call `textFieldDidEndEditing(_:)` it could just take whatever text is currently in the textField. Just a thought – Pierce Jan 12 '17 at 18:05
  • @mosley - I'm sorry it would be `dataReceived = sourceViewController.textField.text` – Pierce Jan 12 '17 at 18:09
  • @brandonscript - Is this what you are asking? It looks like, although I typed `Pass this data`, then pressed the `Return` button, it still returned `Default passed data`. I don't think I can post a screenshot, but is this the property - `dataPassed = (String?) "Default passed data"` – mosley Jan 12 '17 at 18:11
  • @Pierce - Yes, I did try that (mentioned in my original question), and it seemed to work, but I am not sure if thats the "right" way to do it, and it doesn't appear to be the method used in the accepted answer of the question I was trying to follow – mosley Jan 12 '17 at 18:18

1 Answers1

0

I am the asker of that question and fortunately I have a backup of that sample project and here is what I found there. This is what I did in the first view controller

var displayValue: Double{
    get{
        return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
    }
    set{
        display.text?="\(newValue)"
        typing=false
    }
}
@IBAction func unwind(segue: UIStoryboardSegue){
    let foo = segue.sourceViewController as! viewControllerB
    let a = foo.dataSent
    displayValue = NSNumberFormatter().numberFromString(a!)!.doubleValue
}

And it's working fine. Maybe if you can share the sample project you're working on I can see why it's not working? :)

ebby94
  • 3,131
  • 2
  • 23
  • 31
  • @mosley Github, dropbox, etc. Also one question, is the break point coming into `textFieldDidEndEditing` in the ViewControllerB? – ebby94 Jan 13 '17 at 04:18