0

I'm very new in iOS development and I'm stuck on how to save data into the model when accessing several views..

I have a pizza selector (for the sake of this example I'm going to simplify the model), my root file have 2 buttons label as: "Size","Dough", each time you press a button you navigate to a new ViewController within a show segue, in here you have a picker to select from 3 types of sizes or doughs.

What I'm not capable of doing is to save the data from one of the views when returning from the other, I mean, if you press the size button and select for example "large" when you clic on accept it returns to the ViewController class and I have the value of "large" but now if you press on the "Dough" button and select "thin" when you come back it only have the "thin" value the previous size values is lost...

This is the ViewController (root file):

class ViewController: UIViewController {

    let pizza = Pizza(tamano: "", masa: "")

    enum Constantes {
        case Tamano
        case Masa
    }

    @IBOutlet weak var tamanoLabel: UIButton!
    // Almacenamos el tamaño de la pizza
    var tamanoPvara:String?
    var tipoMasa:String?

    // Almacenamos cuales tipos/ingredientes aun no tengo
    var compruebaEleccion = [Constantes.Tamano:false]


    override func viewDidLoad() {
        super.viewDidLoad()
        print("tamano: \(pizza.tamano) masa: \(pizza.masa)")
        // Do any additional setup after loading the view, typically from a nib.
        //        if let (pizza.model["Tamano"] != "") {
        //            labelTamanoPizza.text = pizza.model["Tamano"]
        //        }
    }

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

    @IBAction func btnConfirmacion(sender: AnyObject) {
        // Variable para saber si estan todos los pasos hechos
        print("tamano: \(pizza.tamano) masa: \(pizza.masa)")

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "tamanoPizza") {
            print("tamaño")
            let destinationViewController = segue.destinationViewController as! ViewTamanoController
            destinationViewController.pizza = self.pizza
        }
        if (segue.identifier == "TipoMasa") {
            print("masa")
            let destinationViewController = segue.destinationViewController as! ViewTipoMasaController
            destinationViewController.pizza = self.pizza
        }
    }


}

This is the ViewSizeController:

class ViewTamanoController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {


    @IBOutlet weak var tamanoSelector: UIPickerView!
    @IBOutlet weak var labelTamano: UILabel!

    let pickerData = ["Chica","Mediana","Grande"]

    var pizza = Pizza?()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        tamanoSelector.dataSource = self
        tamanoSelector.delegate = self
    }

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

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        labelTamano.text = pickerData[row]
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "fromTamanoToController") {
            print("segue tamaño")
            let viewController = segue.destinationViewController as! ViewController
//            viewController.tamanoPizza = labelTamano.text;
            viewController.pizza.tamano = labelTamano.text
        }
    }

    @IBAction func btnAceptar(sender: AnyObject) {
//        print("aceptar tamaño")

        pizza!.tamano = labelTamano.text
         print(pizza!.tamano)
    }
}

And this is the ViewDoughController

class ViewTipoMasaController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate  {

    @IBOutlet weak var tipoMasaLabel: UILabel!
    @IBOutlet weak var tipoMasaSelector: UIPickerView!

    let pickerData = ["Delgada","Crujiente","Gruesa"]

    var pizza = Pizza?()


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        tipoMasaSelector.dataSource = self
        tipoMasaSelector.delegate = self

    }

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

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData.count
    }

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerData[row]
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        tipoMasaLabel.text = pickerData[row]
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if (segue.identifier == "fromTipoMasaToController") {
            let viewController = segue.destinationViewController as! ViewController
//            viewController.tipoMasa = tipoMasaLabel.text;
            viewController.pizza.masa = tipoMasaLabel.text
        }
    }

    @IBAction func btnAceptar(sender: AnyObject) {

        pizza?.masa = tipoMasaLabel.text
        print(pizza!.masa)
    }

}

I know this is kind of easy question but any help will be appreciated

Thank you so much

neteot
  • 933
  • 1
  • 12
  • 33
  • Hi, I would use the debugger to see if the viewControllers you get in ViewTamanoController and ViewTipoMasaController are the same as in ViewController. With the debugger you can see if these variables are referencing the same viewController object. If they are not the same, then there is something wrong with the segues. – crom87 Nov 13 '15 at 12:04
  • 1
    Hi @crom87 the thing is that everytime I return from a detail view it loads the first line, that means `let pizza = Pizza(tamano: "", masa: "")` and then the segue method of the detail class update the desire attribute but the previous attribute it get lost everytime the ViewController is load because of the instance `let pizza = Pizza(tamano: "", masa: "")` – neteot Nov 13 '15 at 12:09
  • Thats why I think, that in your detailVC : `let viewController = segue.destinationViewController as! ViewController` you are getting a new ViewController and not the one in backgraound. – crom87 Nov 13 '15 at 12:11
  • Yes, but I don't know how do I get the one on the background?... – neteot Nov 13 '15 at 12:18

2 Answers2

1

I think I found your problem. In the details ViewControllers you are performing a new segue, which means you are creating each time a new parent ViewController. What you have to do is to dismiss the detail View Controller. You don't need the methods prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) in the Details ViewControllers.

Your btnAceptar function would be like that:

@IBAction func btnAceptar(sender: AnyObject) {

        pizza?.masa = tipoMasaLabel.text
        print(pizza!.masa)
        self.dismissViewControllerAnimated(true, completion: nil)
    }

With dismissViewController you are actually returning to the first parent View Controller, and not the new one.

Now, you have to pass the parent ViewController the values for the dough and the size, and you can not do it so easy as you tried. You have to ways of doing that: Notifications or Delegates. You have here an easy example: Pass data when dismiss modal viewController in swift

Instead of the method "backFromCamera" you will have to make a prococol with the methods "setDough" and "setSize" for example.

Have fun ;)

Community
  • 1
  • 1
crom87
  • 1,141
  • 9
  • 18
  • Hi @crom87 thank you!!, finally it works, it's a shame because I don't understand much of the thing I'm doing with the protocols...but I have to read more deep in the documentation, I don't know why I have to set the delegates – neteot Nov 13 '15 at 18:50
0

the reason is because the root view controller is reloading new instance of let pizza = Pizza(tamano: "", masa: "") every time it loads.

take the line let pizza = Pizza(tamano: "", masa: "") out of root view controller or get it from class instance.

  • Hi! @Hussein yes, you're right, but since I am making this app without embedding a navigation controller, I don't have any other root File so I cannot take out that line for the root view but I want to get it from class instance but I don't know how – neteot Nov 13 '15 at 12:19