0

I try to pass a Date from a ViewController to another one through an unwind segue. The problem is that the data passed is replaced by the result of Date().

Here is the code of the VC where the date is selected :

class DateSelectorViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    ...

    @IBAction func validateDate(_ sender: CustomButton) {
        sendDateToNextVC(sender: sender)
    }   

    func sendDateToNextVC(sender: UIButton) {
        let destinationVC = AddActivityViewController()
        destinationVC.dateSelected = dateSelected
        destinationVC.recurrenceType = selectedFrequency
        destinationVC.isRecurrent = recurrent
        performSegue(withIdentifier: "sendSelectedDate", sender: sender)
    } 
}

And here is the code of the VC that receive the date in dateSelected :

class AddActivityViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {

    ...    

    var dateSelected: Date = Date()

    ... 

    @IBAction func unwindToAddActiVC(_ sender: UIStoryboardSegue) {
        if sender.identifier == "sendSelectedDate" {
            setDateLabel()
        }
    } 

    func setDateLabel() {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "fr_FR")
        dateFormatter.dateFormat = "dd MMMM yyyy"
        dateLabel.text = dateFormatter.string(from: dateSelected)
    }

}

I remarked that the line

var dateSelected: Date = Date()

was called multiple times, especially once after that the date was passed from the first VC to the destination VC. I tried using optional but it only leads to obvious errors "found nil while unwrapping".

Please let me know if you need other pieces of code.

Thanks in advance !!

Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
Jonathan
  • 352
  • 2
  • 9

3 Answers3

0

In your sendDateToNextVC method you create a new AddActivityViewController instance, and then just throw it away. iOS doesn't know about it, it just creates another instance. You're setting the date to the instance you created, whereas iOS keeps working with an instance of its own.

You should use prepareForSegue method to pass the date instead. And not create the VC yourself, but get it from the Segue object inside the prepareForSegue method.

It would look something like this:

class DateSelectorViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    ...

    @IBAction func validateDate(_ sender: CustomButton) {
        sendDateToNextVC(sender: sender)
    }   

    func sendDateToNextVC(sender: UIButton) {
        let destinationVC = AddActivityViewController()
        destinationVC.dateSelected = dateSelected
        destinationVC.recurrenceType = selectedFrequency
        destinationVC.isRecurrent = recurrent
        performSegue(withIdentifier: "sendSelectedDate", sender: sender)
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destinationVC = segue.destinationViewController as? AddActivityViewController {
            destinationVC.dateSelected = dateSelected
            destinationVC.recurrenceType = selectedFrequency
            destinationVC.isRecurrent = recurrent
        }
    }
}

More details here: SO: How to pass prepareForSegue: an object

Community
  • 1
  • 1
FreeNickname
  • 7,398
  • 2
  • 30
  • 60
0

DateSelectorViewController must override,

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "sendSelectedDate"{
        var vc = segue.destinationViewController as! AddActivityViewController
        vc.data = "Data you want to pass"
        //Data has to be a variable name in your AddActivityViewController
    }
}
FreeNickname
  • 7,398
  • 2
  • 30
  • 60
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
0

Here you are instantiated a new ViewController and not using the one is the Segue

This part of your code is wrong

func sendDateToNextVC(sender: UIButton) {
        let destinationVC = AddActivityViewController()
        destinationVC.dateSelected = dateSelected
        destinationVC.recurrenceType = selectedFrequency
        destinationVC.isRecurrent = recurrent
        performSegue(withIdentifier: "sendSelectedDate", sender: sender)
    } 

In fact, your are creating a new viewController, the segue do already the job.

Use prepareForSegue instead:

 @IBAction func validateDate(_ sender: CustomButton) {
        sendDateToNextVC(sender: sender)
    }

    func sendDateToNextVC(sender: UIButton) {
        performSegue(withIdentifier: "sendSelectedDate", sender: sender)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "sendSelectedDate",
            let destinationVC = segue.destinationViewController as? AddActivityViewController{
            destinationVC.dateSelected = dateSelected
            destinationVC.recurrenceType = selectedFrequency
            destinationVC.isRecurrent = recurrent
        }
    }

Here you will get the viewcontroller used in the segue, your problem should be solved.

Hope it helps.

Pierre

Pierre Perrin
  • 335
  • 3
  • 13
  • 1
    While I get the use of headers to add structure to a text, with all due respect in your answer there are more headers than text. Please, try to reduce the use of headers. Imagine if all answers were like this. It would be pretty hard to read. Still, thank you for your answer, it's correct. – FreeNickname Mar 07 '17 at 16:43
  • 1
    Thank you very much for your help ! – Jonathan Mar 07 '17 at 21:28