-2

I've tried to read up on many of the postings before but I still seem to not be able to understand "nil".

let mass = Double(density! * volume!)

In this section of the code it tells me:

"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"

When I run my app it runs smoothly if I don't press the button while all the text fields are empty but when I do it crashes and the debugger tool tells me the error is here but I'm not sure why it doesn't work.
I just really don't understand the other nil explanation forums on Stack Overflow and Swift is very confusing for me as it is.

import UIKit
class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var massInput: UITextField!
    @IBOutlet weak var volumeInput: UITextField!
    @IBOutlet weak var densityInput: UITextField!
    @IBOutlet weak var answerOutput: UITextField!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func calculateButton(_ sender: UIButton) {
        clearAnswer()
        mvdCalc()
        clearBoxes()
    }//end of btn

    //------------------------FUNCTIONS-----------------------------------

    func mvdCalc(){
        if massInput.text!.isEmpty {massFormula()}
        if volumeInput.text!.isEmpty {volumeFormula()}
        if densityInput.text!.isEmpty {densityFormula()}
    }//end of mvdCalc

    func clearBoxes(){
        massInput.text = ""
        volumeInput.text = ""
        densityInput.text = ""
    }//end of clear boxes

    func massFormula(){
        let density = Double(densityInput.text!)
        let volume = Double(volumeInput.text!)
        let mass = Double(density! * volume!)
        answerOutput.text = "\(mass)"
    }//end of mass

    func volumeFormula(){
        let density = Double(densityInput.text!)
        let mass = Double(massInput.text!)
        let volume = Double(mass! / density!)
        answerOutput.text = "\(volume)"
    }//end of volume

    func densityFormula(){
        let volume = Double(volumeInput.text!)
        let mass = Double(massInput.text!)
        let density = Double(mass! / volume!)
        answerOutput.text = "\(density )"
    }//end of density

    func clearAnswer() {
        if massInput.text == "" && volumeInput.text == "" && densityInput.text == "" {
            answerOutput.text = ""
        }
    }//end of clearAnswer

}//end of class
Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

2

The app crashes because both density and volume are nil. If you force-unwrap a nil (by using the !), your app crashes.

Why are density and volume nil then?

Because the Double initialisers here returned nil:

let density = Double(densityInput.text!)
let volume = Double(volumeInput.text!)

This is caused by the strings you passed to it being in a wrong format. densityInput.text and volumeInput.text are not valid double strings. Why are they not valid? Well, as you said, the text fields are empty. Empty strings ("") can't be converted to a double.

To fix this, you can choose to not do the calculation if either one of the text fields are not valid:

if let density = Double(densityInput.text!), let volume = Double(volumeInput.text!) {
    let mass = density * volume
    answerOutput.text = "\(mass)"
}

If either is nil, the if won't run.

Do this for all your other calculations as well!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

Yes application will crash for of-course Answers in your question itself

You are calling this as your button Action

@IBAction func calculateButton(_ sender: UIButton) {
    clearAnswer()
    mvdCalc()
    clearBoxes()
}

Step 1 Execution of clearAnswer() Goes well Because you just Clearing your textfields

Step 2 When it comes to mvdCalc() Execution

let mass = Double(density! * volume!)

App crashed here - Look at the following screenshot

enter image description here

if you see Density value is Printed to console are densityStr was not ""

and

Printing mass Produced an Error because massStr was ""

So, To solve You Need to check before calling function to calculate Values

as

if mass != nil {
    print("call function")
    let massValue = Double(density! * volume!)
    answerOutput.text = "\(massValue)"
}
else{
    print("Value is empty no calculation to be performed")
}

Note : Do not clear your TF Values till you had not performed your calculation

Second, Do not call mvdCalc() till required TF for this block is Empty

Show Alert on button press that "Value for this TF is required " and if condition is Satisfied Execute mvdCalc()

iOS Geek
  • 4,825
  • 1
  • 9
  • 30