How to get user-entered data?

Completely frustrated noob here. Surely this isn't as hard as it looks?


I want to use a number entered by the user, perform a calculation on that number when a button is pressed, and send the result back to the screen.


I have the code working that can use a string forced in by code, convert it to double, do the math and send the result to the screen. This simply adds 2.45 to the string "123.45" and sends the result 125.9 back as a string to my label for display, all when the button is pressed. Great.


@IBAction func buttonPressed() {
NSLog("Button Pressed")
let decimalAsString = "123.45" 
let decimalAsDouble = NSNumberFormatter().numberFromString(decimalAsString as String)!.doubleValue 
TempLabel.text = "\(decimalAsDouble+2.45)" }


This simpler form also works:


let decimalAsDouble = Double(decimalAsString)


What I have been struggling with (for way too long) is how to get at the data that was entered into the UITextField. My UITextField uses a decimal pad for entry. I do not yet have code working that dismisses the keyboard and "resigns" the responder. No matter what I try, I cannot find code that will both compile and then not blow up at execution, when the button is pressed.

The error I get generally complains about unwrapping an optional nil. I've always had a number entered when the errors were thrown - the UITextField was not empty - but I have not once succeeded in using the entered value for anything.


My current code example, where the user enters a temperature and ues a picker to select the units for the entered value. The picker part is working pretty well, though certainly not done yet.


import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate
{
    @IBOutlet weak var TempInput: UITextField!
    var TempUnits = ["°F","°C","°K","°R"]
    @IBAction func buttonPressed() {
        NSLog("Button Pressed")
        let decimalAsString = "123.45"
        let decimalAsDouble = Double(decimalAsString)
        TempLabel.text = "\(decimalAsDouble!+2.45)"
}

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

    override func viewDidLoad() {
        super.viewDidLoad()
        func textFieldShouldReturn(textField: UITextField!) -> Bool {   /
            textField.resignFirstResponder()
            return true
        }
     
        TempUnitChoice.tag = 0
        TempUnitChoice.hidden = true
        TempUnitList.text = TempUnits[0]
        TempUnitList.delegate = self
        TempUnitChoice.delegate = self
    }
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int {
        return TempUnits.count
    }
    func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
        return TempUnits[row]
    }
    func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
    {
        TempUnitList.text = TempUnits[row]
        TempUnitChoice.hidden = true
    }
    func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
        TempUnitChoice.hidden = false
        return false
   }

}

It may just be a casualty of trying to copy and paste code into the forums, but it looks like your textFieldShouldReturn() delegate method is trapped inside the scope of your viewDidLoad() method, rather than in the class itself where it should be for it to get called as a method.


If you understand any objective-C, the Hello World iOS sample code is old but might help you figure out the right methods to call:

https://developer.apple.com/library/prerelease/ios/samplecode/HelloWorld_iPhone/Listings/Classes_MyViewController_m.html

Well, I've gotten past this hurdle. The problem was not about referencing the UITextField. My suspicion was right - the problem was that the value entered by the user, although it showed on the screen, wasn't really available yet in the code because the decimal keypad had not been dismissed and the entry field "closed", or whatever the proper term is.


The solution I found was the following code in the viewcontroller:


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
        view.endEditing(true)
        super.touchesBegan(touches, withEvent: event)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        func textFieldShouldReturn(textField: UITextField!) -> Bool {   /
            textField.resignFirstResponder()
            return true
        }


This causes a touch anywhere on screen (other than a button) to dismiss the keypad, and the entered number is ready to use. I still need to handle the case when no value is entered.

The textFieldShouldReturn method should not be defined inside the viewDidLoad() method, it should be outside that method, but inside the class. Although if there is nothing else to do in viewDidLoad() you can just eliminate that altogether.


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

func textFieldShouldReturn(textField: UITextField) -> Bool {
     textField.resignFirstResponder()
     return true
}

Yes, I see, thanks. I've moved it and things still work fine.

How to get user-entered data?
 
 
Q