Bronze Challenge

At first I was not entirely happy with this; it seemed like overkill to turn the newly typed character into a set, but I didn’t see a direct way of checking to see if an individual character was a member of a set. (Although with a bit more digging I found the contains method which would do the trick.)

But if you take cut & paste into account, you could have multiple characters being inserted all at the same time, so turning the replacement string into a set makes more sense in that light.

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool
{
    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")
        
    let replacementTextCharacterSet = CharacterSet(charactersIn: string)
    let replacementTextIsAlphabetic = (replacementTextCharacterSet.isDisjoint(with: CharacterSet.letters) == false)
        
    if (existingTextHasDecimalSeparator != nil &&
        replacementTextHasDecimalSeparator != nil) ||
        replacementTextIsAlphabetic
    {
        return false
    }
    else
    {
        return true
    }
}

I did this a bit differently, without touching the existing checks for the double decimal points, I used a guard at the start of the textField(_:shouldChangeCharactersIn:replacementString:), as follows:

var numbers = CharacterSet.decimalDigits
numbers.insert(charactersIn: ".")
        
guard (string.rangeOfCharacter(from: numbers) != nil) || string.isEmpty else {
    return false
}

I created a CharacterSet of decimal digits (i.e. numbers only) and then also added the “.” to it to make it allowed, too. Then checked for the range of the first character found in the replacementString from the character set. If this is not nil, meaning it did find a valid numeric digit or “.”, OR if the replacementString is empty (which means the user is trying to delete numbers), then continue with the rest of the function, otherwise return false and prevent changes.

The “letters” group from CharacterSet does not include other symbols such as / [ ] ', etc. and these appear to be valid inputs in your solution.

The “letters” group from CharacterSet does not include other symbols such as / [ ] ', etc. and these appear to be valid inputs in your solution.

True. The challenge was to prohibit alphabetic characters so I chose to do only that, and not worry about symbols or other non-alphanumeric characters.

Also, there’s a problem with your implementation that you’re going to find out about in the next chapter.

1 Like