22

I am trying to run this code but I keep on getting this error:

fatal error: unexpectedly found nil while unwrapping an Optional value

I don't understand what it means or why I'm getting it. Any hint?

import UIKit

class ViewController: UIViewController {

var lastNumber: String = ""
@IBOutlet var answerField: UILabel
@IBOutlet var operaterLabel: 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.
}

@IBAction func buttonTapped(theButton: UIButton) {
    if answerField.text == "0"
    {
        answerField.text = theButton.titleLabel.text
    }
    else
    {
        answerField.text = answerField.text + theButton.titleLabel.text
    }
}

@IBAction func plusTapped(theButton: UIButton) {
    // error is talking about the next line
    if operaterLabel.text == ""
    {
        operaterLabel.text = "+"
        lastNumber = answerField.text
        answerField.text = "0"
    }
    else
    {
        enterTapped(nil)
        operaterLabel.text = "+"
    }

}

@IBAction func minusTapped(theButton: UIButton) {
    if operaterLabel.text == ""
    {
        operaterLabel.text = "-"
        lastNumber = answerField.text
        answerField.text = "0"
    }
    else
    {
        enterTapped(nil)
        operaterLabel.text = "-"
    }

}

@IBAction func clearTapped(AnyObject) {
    answerField.text = "0"
    operaterLabel.text = ""
    lastNumber = ""

}

@IBAction func enterTapped(AnyObject?) {

    var num1 = lastNumber.toInt()
    var num2 = answerField.text.toInt()
    if !num1 || !num2
    {
        showError()
        return
    }
    var answer = 0
    if operaterLabel.text == "-"
    {
        var answer = num1! - num2!
    }
    else if operaterLabel.text == "+"
    {
        var answer = num1! + num2!
    }
    else
    {
        showError()
        return
    }
    answerField.text = "\(answer)"

}

func showError()
{
    println("Ther was an error")
}
}
Brian
  • 14,610
  • 7
  • 35
  • 43
Arshia
  • 223
  • 1
  • 2
  • 4

11 Answers11

17

the error refers to the fact that you're accessing the parameter of an optional value when the optional value is set to nil (e.g. accessing answerField.text when answerField is nil), likely one of your two UILabels.

If the line operaterLabel.text == "" is throwing the exception, then your operaterLabel is nil. Verify that you have connected it successfully to the label in your Interface Builder file.

Ankit Vij
  • 274
  • 3
  • 12
jmduke
  • 1,657
  • 1
  • 13
  • 11
  • 1
    So if the erorr is highlighting this: if operaterLabel.text == "" in fuction plusTapped whats the problem – Arshia Jul 25 '14 at 05:05
7

some times the problem that you have initiate view controller before present it like this:

let myViewController  = MyViewController()

replace that by

let  myViewController = self.storyboard?.instantiateViewController(withIdentifier: "storyboardID") as! MyViewController
Ahmad Labeeb
  • 1,056
  • 11
  • 21
  • I logged in to vote for this answer. This solved it in my case. – Nora Mar 28 '18 at 11:53
  • I've done a bit of research as to why this works. This threw me for a loop at first as I've persisted data using the top line of code when creating a view programmatically and not utilizing storyboard. It seems the view needs to be explicitly created utilizing storyboard for @IBOutlets to be linked to the UIViewController class. You can however use the top line of code if you are not utilizing storyboard for the ViewController you're creating an instance of. – JohnAnge Kernodle Jul 04 '22 at 16:42
6

In my case, I was trying to access the labels in a function that I created which was used after the set of a variable.

var something: String {
    didSet {
        updateUI()
    }
}

func updateUI() {
    label.text = "Hello"
}

I solved it by:

var something: String

override func viewDidLoad() {
    label.text = "hello"
}

My theory is that my function updateUI was accessed before the views and labels were created.

Nati Lara-Diaz
  • 2,056
  • 16
  • 8
5

check your outlets, I've had this before labels and buttons can just become dis connected (if for instance you have adjusted constraints ect)

a simple re connection can sometimes fix the issue

Richy Garrincha
  • 277
  • 5
  • 17
  • You can do this by opening up the storyboard file and opening the connections inspector in the utility pane (circle with right arrow icon). The connections are listed (and can be created) under the "Referencing Outlets" section (XCode 7.1). – Aaron D Nov 01 '15 at 07:01
4

If you make sure the xib for your cell is no problem,

Then I occur this issue, my error was register the cell method :

1)

self.tableView.register(TerantInfoTabCell.self, forCellReuseIdentifier: "TerantInfoTabCell")

2)

self.tableView.register(UINib(nibName:"TerantInfoTabCell", bundle: nil), forCellReuseIdentifier: "TerantInfoTabCell")

I use the first method, there will appear the issue,then I use the 2) method replace the 1) , so there is no problem here.

aircraft
  • 25,146
  • 28
  • 91
  • 166
2

I had the exact same error and spent quiet an amount of time debugging it. What @jmduke said is really the key: where does the error occur?

With my particular error, looking at operaterLabel.text == "" led me on the right path. I accessed the operaterLabel.text while the view was not yet fully initialized. In my particular case I set a variable from a different view during a segue and then acted upon that variable being set and updating a label inside the view. However the view was not completely initialized.

Thus my solution was to update the label inside the viewDidLoad() function.

Christoph Eicke
  • 1,134
  • 7
  • 15
1

I searched and searched trying to figure out how to solve my similar problem. As others mentioned, I was accessing UI elements before they were initialized. But figuring out why, was the difficult part. Spoiler --> I was using ProfileVC.swift and profileVC.xib

Even though I had all of my connections right in IB, from the parentVC I was calling

let newVC = ProfileVC()
profile.modalPresentationStyle = .custom
present(profile, animated: true, completion:nil)

Since I had different names (caplital 'P' in my swift file and lowercase 'p' in my xib), calling ProfileVC() didn't work as it didn't know to go to the xib I had made. Instead I had to use:

let newVC = ProfileVC.init(nibName: "profileVC", bundle: Bundle.main)

or just rename the xib to have a captial P and I could use my original code

Obviously this is hard to see in stackoverflow as you need to see what you are calling in the parent VC, the names of the files and IB. So hopefully this may be one solution to someone's problem out there even if it doesn't solve Arshia's problem.

Kevin Veverka
  • 153
  • 1
  • 7
0

That means your storyboard doesn't have a link to your IBOUTLET, please verify

Medhi
  • 2,656
  • 23
  • 16
0

I had this error and my problem was caused by adding a member (let's call it newProperty) to my model class, then trying to run a project that loaded data with NSCoder.decodeObjectForKey(newPropertyKey). During previous testing, I had saved objects without newProperty, so when the app tried to call decodeObjectForKey(newPropertyKey) on my old data, Xcode responded with this error message.

Christopher Garcia
  • 2,536
  • 7
  • 30
  • 40
0

This error usually occurs because we try to change UILabel text after the view is loaded. Remember that UILabels once loaded in the view cannot be changed in any way they can only be set within viewdidload() function. You can check this by putting your text assigning code in the viewDidLoad() function which will set UILabels when loading the view, It will work. But now if your application is built in such a way that it is setting UILabels after the view is loaded then the only solution is that you will need to create UILabels dynamically/Programatically where ever you want in the code and assign what ever you want because they will be created/instantiated with that text/label.

0

As @aircraft said you can register your cell this way :

let cellNib = UINib(nibName: "\(CellClass.self)", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "\(CellClass.self)")

this solved the problem with me.

A_Mo
  • 338
  • 2
  • 8