PSidhu PSidhu - 5 months ago 30
Swift Question

iOS Delegate to prevent invalid inputs

I'm learning iOS development and am trying to prevent a UITextField to have values which have multiple decimal values such as "45.3.1" and alphabetical characters.

The preventing of alphabetical characters functionality is not working as I intended. If I print

alphabeticString
when entering a number in the text field I get
nil
though when I print
alphabeticString
when entering a character such as 'a' I get an optional range. For some reason my if statement always returns true when there is a character inserted even when
alphabeticString
prints as nil.

Any reasons why? Thanks.

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

let existingTextHasDecimalSeperator = textField.text?.rangeOfString(".")
let replacementTextHasDecimalSeparator = string.rangeOfString(".")
let alphabeticString = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet())

if existingTextHasDecimalSeperator != nil && replacementTextHasDecimalSeparator != nil && alphabeticString != nil {
return false
}
else {
return true
}
}

Answer

Hmm, I'm not sure why that isn't working. Why don't you use a 'Decimal Pad' keyboard type for your textfield?

If for some reason you don't want to, try this:

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

    switch string {
    case "0","1","2","3","4","5","6","7","8","9":
        return true
    case ".":
        if let _ = textField.text?.rangeOfString("."){
            return false
        }else{
            return true
        }
    default:
        if let _ = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()){
            return false
        }

        return true
    }
}

EDIT: I think I found the problem in your code, you need to separate the if statement into two conditions:

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

    let existingTextHasDecimalSeperator = textField.text?.rangeOfString(".")
    let replacementTextHasDecimalSeparator = string.rangeOfString(".")
    let alphabeticString = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet())

    if (existingTextHasDecimalSeperator != nil && replacementTextHasDecimalSeparator != nil) ||  alphabeticString != nil {
        return false
    }
    else {
        return true
    }
}