Update textfield with current contents

Hi there, I am trying to write part of a simple code to return either Celcius or Fahrenheit using a segemented control to switch between the two. If I enter a value into the textbox and switch the segmented control, it works great. However, when I try and switch back to the original case, it acts as if there is no text in the textfield and returns to the default value, 0.0. Essentially, I'd like it to check the textfield for text, not just require new text to be entered. Thanks in advance.


Here's the code:


@IBAction func tempConvert(_ sender: UISegmentedControl) {

switch sender.selectedSegmentIndex {

case 0:

temperature = Float(temperatureField.text!) ?? 0.0

let celsius = Measurement(value: (Double(100*((temperature - 32) / 1.8).rounded() / 100)), unit:UnitTemperature.celsius)

print(celsius)

temperatureField.text = String(describing: celsius)

checkTempUnits = true

case 1:

temperature = Float(temperatureField.text!) ?? 0.0

let fahrenheit = Measurement(value: (Double(100*((temperature * 1.8) + 32).rounded()/100)), unit: UnitTemperature.fahrenheit)

temperatureField.text = String(describing: fahrenheit)

checkTempUnits = false

default:

speed = Float(331 + (0.6 * temperature))

}

}

Replies

when I try and switch back to the original case, it acts as if there is no text in the textfield and returns to the default value, 0.0.

Similar to the issue that you have once exeperienced when working with length.

`Float(temperatureField.text!)` generates nil when the text includes non-number like `°C`, and `?? 0.0` converts to the default value 0.0.


One way is to split up `unit` to a separate label or textField as suggested in your other thread.


Another way, using Scanner to ignore postfixed unit:

    let temperatureFormatter: MeasurementFormatter = {
        let mf = MeasurementFormatter()
        mf.unitOptions = .providedUnit
        mf.unitStyle = .medium
        //You may want this to prevent thousand separators
        let nf = NumberFormatter()
        nf.usesGroupingSeparator = false
        mf.numberFormatter = nf
        return mf
    }()
    
    @IBAction func tempConvert(_ sender: UISegmentedControl) {
        
        let temperatureText = temperatureField.text ?? ""
        let scanner = Scanner(string: temperatureText)
        scanner.locale = Locale.current
        guard let temperatureValue = scanner.scanFloat() else {
            print("bad value: \(temperatureText)")
            //Show some alert for user?
            return
        }
        print(temperatureValue)
        
        switch sender.selectedSegmentIndex {
        case 0:
            
            temperature = temperatureValue
            
            let celsius = Measurement(value: (Double(100*((temperature - 32) / 1.8).rounded() / 100)), unit:UnitTemperature.celsius)
            print(celsius)
            temperatureField.text = temperatureFormatter.string(from: celsius)
            
        case 1:
            
            temperature = temperatureValue
            let fahrenheit = Measurement(value: (Double(100*((temperature * 1.8) + 32).rounded()/100)), unit: UnitTemperature.fahrenheit)
            temperatureField.text = temperatureFormatter.string(from: fahrenheit)
            
        default:
            //???
            break
        }
    }

That's because temperatureField.text contains both the value and the unit (°C or °F).

So, when you try

            temperature = Float(temperatureField.text!) ?? 0.0

Float returns nil (not a number) and temperature is set to zero.

That is something you had already seen in a previous thread.


So, look at this other thread or

You could store the value you entered in a var as Double for the Celcius value for instance.


Then, in tempConvert, you read this value:

- use directly if toggle to Celcius

- compute farenheit from this value


If you enter value when in farenheit mode, convert to Celcius to save in var.