My Bronze Challenge

#1

Hi guys,

Here’s my solution to the Bronze challenge:

 func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
    
    //If the string already has a decimal, and the user inputs a new decimal, 
    //reject the latest decimal
    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.contains(".")
    
    if existingTextHasDecimalSeparator != nil &&
        replacementTextHasDecimalSeparator != false {
        return false
    }
    
    //If there is an invalid character, return false
    let invalidCharacters = CharacterSet(charactersIn: "0123456789.").inverted
    let replacementTextHasLetters = string.rangeOfCharacter(from: invalidCharacters)
    
    if replacementTextHasLetters != nil {
        return false 
    }

    return true

 }

I’m sure there’s a way to make it more elegant but I figured I’d put both checks in separate pieces since this is for learning after all.

#2

Minor change to use NSCharacterSet.letters

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    //print("Current text: \(textField.text)")
    //print("Replacement text: \(string)")
    
    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")
    let replacementTextHasLetter = string.rangeOfCharacter(from: NSCharacterSet.letters)
    
    if replacementTextHasLetter != nil {
        return false
    }
    
    if existingTextHasDecimalSeparator != nil, replacementTextHasDecimalSeparator != nil {
        return false
    }
    
    return true
}
#3

This worked for me. Only allows for 1 decimal point and numeric characters.

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

    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")
    
    let decimal = CharacterSet(charactersIn: ".0123456789").inverted
    let replacementTextHasAlphabet = string.rangeOfCharacter(from: decimal)

    if existingTextHasDecimalSeparator != nil, replacementTextHasDecimalSeparator != nil {
        return false
    } else if replacementTextHasAlphabet != nil {
        return false
    } else {
        return true
    }
}
#4

Hi everyone!
I did it using NSCharacterSet as the book says:

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

    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")
    let validDigits = string.rangeOfCharacter(from: CharacterSet.decimalDigits)

    if validDigits != nil
        || (replacementTextHasDecimalSeparator != nil && existingTextHasDecimalSeparator == nil)
        || range.length > 0
    {
        return true
    }
    else
    {
        return false
    }
}

Well, I’ve exactly used CharacterSet to code this solution and the range.length > 0 condition to check backspaces.
Hope it’ll be useful :wink: .