0

I am new to Swift, I am currently reading the Big Nerd Ranch book to understand more. I have an application that allows the user to type the temperature in Fahrenheit then will be converted to Celsius and displayed on the interface. The application only displays one fractional digit on the Celsius label. Now I want to disallow the user from entering the alphabetic characters. I have been trying to figure out how to do so but I wasn't able to get the idea. Any help would be much appreciated. Here is my code so far:

import UIKit

class ConversionViewController : UIViewController , UITextFieldDelegate {

@IBOutlet var textField: UITextField!
@IBOutlet var celsiusLabel: UILabel!
var fahrenheitValue: Measurement<UnitTemperature>? 
{
didSet {
       updateCelsiusLabel()
       }
}

  var celsiusValue: Measurement<UnitTemperature>? {
  if let fahrenheitValue = fahrenheitValue {
    return fahrenheitValue.converted(to: .celsius)
    } else {
        return nil
    }
           }

    func updateCelsiusLabel() {
    if let celsiusValue = celsiusValue {
    celsiusLabel.text = numberFormatter.string(from: NSNumber(value: celsiusValue.value))
    } else {
        celsiusLabel.text = "???"
    }
    }

    let numberFormatter: NumberFormatter = {
    let nf = NumberFormatter()
    nf.numberStyle = .decimal
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
    }()

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool {

        let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
        let replacementTextHasDecimalSeparator = string.range(of: ".")

        if existingTextHasDecimalSeparator != nil,
            replacementTextHasDecimalSeparator != nil {
            return false
        } else {
            return true
        }
}
      @IBAction func fahrenheitFieldEditingChanged(_ textField: UITextField) {

    if let text = textField.text, let value = Double(text) {
        fahrenheitValue = Measurement(value: value, unit: .fahrenheit)
    } else {
        fahrenheitValue = nil
    }
} 
   @IBAction func dismissKeyboard(_ sender: UITapGestureRecognizer) {
    textField.resignFirstResponder()
}

    override func viewDidLoad() {
    super.viewDidLoad()
    updateCelsiusLabel()
}
}
D.Moses
  • 59
  • 1
  • 2
  • 7

3 Answers3

0

You already have the function:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool

Simply change it to return false using this:

for tempChar in string.unicodeScalars {
    if tempChar.isAlpha() {
        return false
    }
}
Oskar
  • 3,064
  • 2
  • 21
  • 33
  • Since the goal is to allow a user to enter only a decimal number, a better check is to only allow digits and the appropriate decimal separator. Simply disallowing letters still allows for many other invalid characters. – rmaddy Apr 26 '17 at 14:34
0

Here's my solution which builds on the book's if statement by going another layer deep.

if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {
    return false
}
else {
    if CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string)) || (string.range(of: ".") != nil) {
    // If incoming character is a decimalDigit or a period, return true
    return true
    }
    else {
        // If a letter is detected, returns false
        return false
    }
}
Jeremy
  • 689
  • 5
  • 11
-2

You can set the keyboardType of a UITextField to various UIKeyboardTypes that will change the input options available to the user. The different keyboard types are listed in the Apple docs here: https://developer.apple.com/reference/uikit/uikeyboardtype

Rob T
  • 137
  • 1
  • 6