Search code examples
swift3option-typeuisegmentedcontrol

Crashing with 'unexpectedly found nil while unwrapping an optional' on UISegmentedControl setTitle method


I have a sourceViewController which is accessing a UISegmentedControl in destinationViewController. EventType is an enum defined as:

enum EventType: Int {
    case Rashifal, RashiGyan
}

The title of segmentedControl on destinationViewController should change according to the change of the value of segmentedControl on sourceViewController.

Whenever the segmentedControl is tapped in sourceViewController, value changed is seen, as I have printed in the console. Now, I want to change the content of segmentedControl in destinationViewController according to the previously selected segmentedControl value in my sourceViewController.

The value of segmentedControl in destinationViewController works fine on the first run and as expected, but when I navigate to my sourceViewController and change the segmentedControl and navigate to destinationViewController, there's a crash with message Fatal error: unexpectedly found nil while unwrapping an Optional value in a console.

Here's how I have tried to change the value of my segmentedControl in destinationViewController from sourceViewController.

 @IBAction func segmentedControlValueChanaged(_ sender: UISegmentedControl) {
    let eventType = EventType(rawValue: sender.selectedSegmentIndex)!

    let anotherVC = UIStoryboard(name: "Rashifal", bundle: nil).instantiateViewController(withIdentifier: "RashiDetailVC") as? RashiDetailVC
    switch eventType {
    case .Rashifal:
        print("at Rashifal")
        anotherVC?.segmentedControl.setTitle("दैनिक", forSegmentAt: 0)
        anotherVC?.segmentedControl.setTitle("साप्ताहिक", forSegmentAt: 1)
        anotherVC?.segmentedControl.setTitle("मासिक", forSegmentAt: 2)
        anotherVC?.segmentedControl.setTitle("वार्षिक", forSegmentAt: 3)
    case .RashiGyan:
        print("At RashiGyan")
        anotherVC?.segmentedControl.setTitle("विशेषता", forSegmentAt: 0)
        anotherVC?.segmentedControl.setTitle("शुभ/अशुभ", forSegmentAt: 1)
        anotherVC?.segmentedControl.setTitle("प्रेम", forSegmentAt: 2)
        anotherVC?.segmentedControl.setTitle("जीवन", forSegmentAt: 3)
    }

}

What might have possibly gone wrong?


Solution

  • To pass data to a VC that you are going to show, do not use the instantiateViewController method. That will give you a new VC, instead of the one that is going to be presented.

    First, make a variable called eventType in the destination controller:

    var eventType: EventType!
    

    Override prepareForSegue in source VC:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // make segmentedControl as an IBOutlet if you haven't done already
        let eventType = EventType(rawValue: segmentedControl.selectedSegmentIndex)!
        if let vc = segue.destination as? RashiDetailVC {
            vc.eventType = eventType
        }
    }
    

    In the destination VC's viewDidLoad, do the switch statement:

            switch eventType {
            case .Rashifal:
                print("at Rashifal")
                segmentedControl.setTitle("दैनिक", forSegmentAt: 0)
                segmentedControl.setTitle("साप्ताहिक", forSegmentAt: 1)
                segmentedControl.setTitle("मासिक", forSegmentAt: 2)
                segmentedControl.setTitle("वार्षिक", forSegmentAt: 3)
            case .RashiGyan:
                print("At RashiGyan")
                segmentedControl.setTitle("विशेषता", forSegmentAt: 0)
                segmentedControl.setTitle("शुभ/अशुभ", forSegmentAt: 1)
                segmentedControl.setTitle("प्रेम", forSegmentAt: 2)
                segmentedControl.setTitle("जीवन", forSegmentAt: 3)
            }
    

    This ensures that the segmented control has been initialised before you set its title.