Jenny
Jenny

Reputation: 45

App crashing because of no values in the uiTextfield

When I enter a value in the UiTextField and press add button the app works perfectly fine,but when I don't enter a value in the UiTextField, then press the add button the whole app crashes. can someone please help me and show me the light.Thank you in advance and good wishes for you and your family.

This is my code

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

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

        self.textFild.delegate = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    @IBOutlet var textFild: UITextField!

    @IBAction func ButtonAwesome(sender: AnyObject) {



        let value:Double = Double(textFild.text!)!


        let sum:Double = value - 1;



        let alert = UIAlertController(title: "km", message:  "\(sum)", preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: "Exit", style: UIAlertActionStyle.Default, handler: nil))
        self.presentViewController(alert,animated: true, completion: nil)



    }


    func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString stringer: String) -> Bool
    {

        if (textField.text == "" && (stringer == ".")) {
            return false;
        }


        let countdots = textField.text!.componentsSeparatedByString(".").count - 1

        if countdots > 0 && stringer == "."
        {
            return false
        }


        return true
    }




}

Upvotes: 2

Views: 1966

Answers (3)

dfrib
dfrib

Reputation: 73176

A more robust solution would be to use the nil coalescing operator to assert that the initialization of value never fails.

@IBAction func ButtonAwesome(sender: AnyObject) {
    let value = Double(textFild.text ?? "0") ?? 0
    let sum:Double = value - 1;

    let alert = UIAlertController(title: "km", message:  "\(sum)", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Exit", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert,animated: true, completion: nil)
}

This is valid for any of the following "unexpected" values of textField.text: nil, "" (empty) or some character that cannot be used to initialize a Double type variable (e.g. "a"). For all these cases, value is give a value of 0.


As an example, consider the following comparisons between a safe and an un-safe way of solving your initial runtime exception.

We first look at the dangers of forcibly unwrapping optionals - not a safe solution. What if textField.text contains nil or an non-numerical character, e.g. "a"? Result:

var myTextFieldText : String? = nil

/* Example 1: nil value causes runtime error */
if myTextFieldText != "" { // this is 'true' -> enter if closure
    let value:Double = Double(myTextFieldText!)!
    /* this will fail at run time since we are forcibly (un-safely)
       unwrapping an optional containing 'nil'                           */
}

/* Example 2: non-numeric string character causes runtime error */
myTextFieldText = "a"
if myTextFieldText != "" { // this is 'true' -> enter if closure
    let value:Double = Double(myTextFieldText!)!
    /* this will fail at run time since we cannot initalize a
       Double with a string value "a", hence 'Double(myTextFieldText!)'
       returns nil, but since we've appended '!', we, like above,
       forcibly tries to unwrap this optional of value nil              */
}

You should, generally, always use conditional unwrapping of optionals, to avoid encountering a nil value when forcibly unwrapping optionals, the latter leading to a runtime error.

A more robust version of the example above, making use of the nil coalescing operator:

myTextFieldText = nil

let valueA = Double(myTextFieldText ?? "0") ?? 0 // 0
/* OK, Double(myTextFieldText ?? "0") = Double("0") = 0                  */

myTextFieldText = "a"
let valueB = Double(myTextFieldText ?? "0") ?? 0 // 0
/* OK, Double(myTextFieldText ?? "0") = Double("a") = nil (fails)
    => use rhs of outer '??' operator: nil ?? 0 = 0                      */

For an alternative method, where you extend UITextField to cover your string to numerical type conversion needs, see Leos neat answer in the following thread:

The thread also contains some other valuable insights w.r.t. reading text as numerical values from UITextField instances.


Finally, when dealing with String to Double value conversion, it might be appropriate to use a fixed precision w.r.t. number of decimal digits in your resulting Double value. For a thorough example of how to do this using NSNumberFormatter and extensions, see:

Upvotes: 2

VIP-DEV
VIP-DEV

Reputation: 221

Since textfield.text is an optional value and as in your case textfield can or cannot have text. So you should test for optional as give below.

if let textIsAvailable = textfield.text
{
        print("Text \(textIsAvailable)")
}

Note : The reason for your crash is you are trying to access value which actually doesn't have any value.

Upvotes: 0

Nata Mio
Nata Mio

Reputation: 2228

Please replace your buttonAwesome method with the following code where you check if textfield is not empty, this will work if textfield has a value:

@IBAction func ButtonAwesome(sender: AnyObject) {

    if textFild.text != "" {

    let value:Double = Double(textFild.text!)!


    let sum:Double = value - 1;


    let alert = UIAlertController(title: "km", message:  "\(sum)", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Exit", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert,animated: true, completion: nil)

    }

}

Upvotes: 1

Related Questions