0

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)"
        }
Code Different
  • 90,614
  • 16
  • 144
  • 163
RufusV
  • 408
  • 3
  • 17
  • I think you should change your if statement with `||` instead of `&&` because if your textField A and B are not nill but C you won't catch this error, also you can protect the entries in your textField with guard statement for instance : `guard let textA = textFieldA.text else { print("no textFieldA") }` – Chajmz Jul 02 '16 at 00:06
  • 1
    When it crashes, what input values are you using? – Tom Harrington Jul 02 '16 at 00:27

2 Answers2

1

Your if statement checks if all of the values are nil. You want to see if any of them are nil.

Change the if to:

if a == nil || b == nil || c == nil {

I don't program in Swift but I get the impression there are lots of other improvements you should make to verify that values are not nil.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

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.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • I think you can combine the "let" lines with the guard statement. That should handle the nil checks automatically. i.e "guard let a = blah, b = blah, c = blah else" – ghostatron Jul 02 '16 at 00:37
  • You can do it, I'm sure of it. I've done it countless times, and the aesthetics would depend on the situation. For longer statements, yeah it's ugly. Don't do it. But for a "sanity" check for method inputs at the start of a method, it's excellent. – ghostatron Jul 02 '16 at 00:51
  • You are right, and it avoids needing to force unwrap a, b & c everywhere. Thanks – Paulw11 Jul 02 '16 at 01:00