Search code examples
swiftforced-unwrapping

found nil while unwrapping an ViewController Optional


I am building a very simple swift application that uses two view controllers - "ViewControler" and "AnimalChooserViewControler". First has a simple label and a toolbar with one item, which transfers the user to the second screen. In the second, have custom picker. The whole purpose of the app is to display whatever the user has selected from the second view controler to the first one using the output UILabel. I have to mention that I am usong xCode 6.4 (ios8)

My problem is when I try to cast the presentedViewController as! ViewController the app crashes with "fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)" exceptions. How to solve this problem, any suggestions? Here is my code in the ViewControler:

class ViewController: UIViewController {
@IBOutlet weak var outputLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

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

func displayAnimal(choosenAnimal: String, withSound choosenSound: String, fromComponent choosenComponent: String){
    self.outputLabel.text = "You changed \(choosenComponent) (\(choosenAnimal)(and the sound \(choosenSound))"
}

}

And this is my code in AnimalChooserViewControler

class AnimalChooserViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate{

let kComponentCount: Int = 2
let kAnimalComponent: Int = 0
let kSoundComponent: Int = 1

var animalNames: [String] = []
var animalSounds: [String] = []
var animalImages: [UIImageView] = []

@IBAction func dismisAnimalChooser(sender: AnyObject) {
    dismissViewControllerAnimated(true, completion: nil)
}

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
    return kComponentCount
}

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if component == kAnimalComponent{
        return animalNames.count
    } else {
        return animalSounds.count
    }
}

func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {

    if component == kAnimalComponent {
        let choosenImageView: UIImageView = animalImages[row]

        let workarroundImageView: UIImageView = UIImageView(frame: choosenImageView.frame)
        workarroundImageView.backgroundColor = UIColor(patternImage: choosenImageView.image!)

        return workarroundImageView
    } else {
        let soundLabel: UILabel = UILabel(frame: CGRectMake(0, 0, 100, 32))
        soundLabel.text = animalSounds[row]

        return soundLabel
    }
}

func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
    return 55.0
}

func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
    if component == kAnimalComponent{
        return 75.0
    } else {
        return 150.0
    }
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    let initialView : ViewController = presentedViewController as! ViewController

    if component == kAnimalComponent{
        let choosenSound: Int = pickerView.selectedRowInComponent(self.kSoundComponent)
        initialView.displayAnimal(animalNames[row], withSound: animalSounds[choosenSound], fromComponent: "the Animal")
    } else {
        let choosenAnimal: Int = pickerView.selectedRowInComponent(kAnimalComponent)
        initialView.displayAnimal(animalNames[choosenAnimal], withSound: animalSounds[row], fromComponent: "the Sound")
    }


}




override func viewDidLoad() {
    super.viewDidLoad()

    animalNames = ["Mouse","Goose","Cat","Dog","Snake","Bear","Pig"]
    animalSounds = ["Oink","Rawr","Sss","Meow","Honk","Squeak"]
    animalImages = [UIImageView(image: UIImage(named: "mouse.png")),
        UIImageView(image: UIImage(named: "goose.png")),
        UIImageView(image: UIImage(named: "cat.png")),
        UIImageView(image: UIImage(named: "dog.png")),
        UIImageView(image: UIImage(named: "snake.png")),
        UIImageView(image: UIImage(named: "bear.png")),
        UIImageView(image: UIImage(named: "pig.png"))]

    preferredContentSize = CGSizeMake(340,380)

}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let initialView: ViewController = presentedViewController as! ViewController
    initialView.displayAnimal(animalNames[0], withSound: animalSounds[0], fromComponent: "nothing yet...")


}

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


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/

}

Solution

  • I found what was causing the exception. I have used "presentedViewController" instead of "presentingViewController". Silly mistake but it took me a good hour to find it out :)