Search code examples
iosswiftquadraticexc-bad-instruction

In my equation solving program, inputting nil value crashes app


I have made an app that solves quadratic equations (just to see if I could), however, I don't want the app to crash if the user accidentally inputs no value for one of the slots. Please help.

 @IBAction func solveButton(sender: AnyObject) {

        let a:Double! = Double(textFieldA.text!)      // textfieldA is UITextField
        let b:Double! = Double(textFieldB.text!)    // textfieldB is UITextField
        let c:Double! = Double(textFieldC.text!)   // textFieldC is UITextField

        // This is for if the a value is nil
        if a == nil && b == nil && c == nil{

            errorTextField.text = "Please do not leave an empty value, all quadratic equations must have 3 values!"
            answerLabel.text = " "

            answerLabelNegative.text = " "
            whatEquation.text = " "
            return

        } else {

            let a:Double! = Double(textFieldA.text!)      // textfieldA is UITextField
            let b:Double! = Double(textFieldB.text!)    // textfieldB is UITextField
            let c:Double! = Double(textFieldC.text!)   // textFieldC is UITextField
            let x:Double = (b * b)
            let y:Double = -4 * a * c //Here I get EXC_BAD_INSTRUCTION error
            let xy:Double = x + y
            let az:Double = sqrt(xy)
            let finalTopPlus:Double = -b + az
            let finalTopMinus:Double = -b - az
            let aTwo:Double = 2 * a
            let finalEquationPositive:Double = finalTopPlus / aTwo
            let finalEquationNegative:Double = finalTopMinus / aTwo

            answerLabel.text = "Positive x = \(finalEquationPositive)"
            answerLabelNegative.text = "Negative x = \(finalEquationNegative)"

            let aValue = a < 0 ? "-" : " "
            let bValue = b < 0 ? " " : "+"
            let cValue = c < 0 ? " " : "+"
            whatEquation.text = "Equation: \(aValue) \(a)x² \(bValue) \(b)x \(cValue) \(c)"
        }

Solution

  • In Swift, you should consider carefully whether you want to force unwrap (!) a value or conditionally unwrap a value (?) - As force unwrapping a nil will give you a run time exception.

    For example, take one of your first lines. This should probably be:

    let a = Double(textFieldA.text!)
    

    This will result in a being a Double? - i.e. it is optional, so it may be nil. It is OK to force unwrap the textFieldA.text value since this will be set by your storyboard (or however you make the text field) and a nil value here represents a serious error that you need to investigate and resolve.

    Once you have optionals you can use the Swift guard statement to check for nil. After you have used the guard statement you can safely use ! to force unwrap the values since you know they aren't nil.

    @IBAction func solveButton(sender: AnyObject) {
    
        guard let a = Double(textFieldA.text!), 
              let b = Double(textFieldB.text!),
              let c = Double(textFieldC.text!) else {
            errorTextField.text = "Please do not leave an empty value, all quadratic equations must have 3 values!"
            answerLabel.text = " "
            answerLabelNegative.text = " "
            whatEquation.text = " "
            return
        }
    
        let x = (b * b)
        let y = -4 * a * c 
        let xy = x + y
        let az = sqrt(xy)
        let finalTopPlus= -b + az
        let finalTopMinus = -b - az
        let aTwo= 2 * a
        let finalEquationPositive = finalTopPlus / aTwo
        let finalEquationNegative = finalTopMinus / aTwo
        answerLabel.text = "Positive x = \(finalEquationPositive)"
        answerLabelNegative.text = "Negative x = \(finalEquationNegative)"
    
        let aValue = a < 0 ? "-" : " "
        let bValue = b < 0 ? " " : "+"
        let cValue = c < 0 ? " " : "+"
        whatEquation.text = "Equation: \(aValue) \(a)x² \(bValue) \(b)x \(cValue) \(c)"
    }
    

    Note that in Swift you only need to define the type of a variable or constant if it can't be inferred. Double() returns an optional Double, and the result of adding two Doubles is a Double, so you don't need to state that the constant will be a Double.