My Bronze Challenge isn't quite right

#1

I’ve tried the following for the Bronze Challenge, but I can still enter “stuff” into the text field.

Here’s my code. How should I modify it?

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
    let existingTextHasDecimalSeparator = textField.text?.rangeOfString(".")
    let replacementTextHasDecimalSeparator = string.rangeOfString(".")
    let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
    
    
    if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil && textField.text?.rangeOfCharacterFromSet(badCharacters) != nil {
        return false
    }
    else {
        return true
    }
  
}
#2
let string = "stuff"
let existingTextHasDecimalSeparator = string.rangeOfString(".")   //=> nil
existingTextHasDecimalSeparator != nil  //=> false

So, what does your function return? true or false? (Hint: If one conditional in a series of && conditionals evaluates to false then the whole conditional evaluates to false.)

I suggest that you stick with single conditional if statements.

#3

It still returns true in all cases.

If I type in a number with a single decimal, it converts the temperature properly.

When I try to add another decimal, it does not appear.

However, when I type in single words, they still appear in the text field.

#4

Right. I showed you why with a simple code example. You can add an if statement that rejects text containing characters–before any other if statements. It’s simpler and easier to understand the code if you create a series of single conditional if statements that reject the text if it does not meet your requirements, e.g.

if <some conditions here> {
   return false
}
#5

I’m closer…however, I can still enter an initial non-numeric character (though, nothing afterwards, and nothing after a decimal).

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
    let existingTextHasDecimalSeparator = textField.text?.rangeOfString(".")
    let replacementTextHasDecimalSeparator = string.rangeOfString(".")
    let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
    
    let existingTextHasLetter = textField.text?.rangeOfCharacterFromSet(badCharacters)
    let replacementTextHasLetter = string.rangeOfCharacterFromSet(badCharacters)
    
    // if there's any text other than a number or a ".", don't want to see anything
    if existingTextHasLetter != nil && replacementTextHasLetter != nil {
        return false
    }
    
    if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {
        return false // return false if there's a "." in the current text and a "." thereafter
    }
    else {
        return true
    }
  
}
#6

Suppose textField.text? is equal to "", and then you type an “h”, i.e. string = "h". What does your function do?

let existingTextHasLetter = textField.text?.rangeOfCharacterFromSet(badCharacters)  //=> nil
if existingTextHasLetter != nil  ... //=> false
#7

Trying that, the “h” didn’t go through, but neither did a “.”

I tried something different with the if statements and ended up with a proper solution:

  func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
    let existingTextHasDecimalSeparator = textField.text?.rangeOfString(".")
    let replacementTextHasDecimalSeparator = string.rangeOfString(".")
    let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
    let replacementTextHasLetter = string.rangeOfCharacterFromSet(badCharacters)
    
    // if there's any text other than a number or a ".", don't want to see anything
    
    if (existingTextHasDecimalSeparator != nil && replacementTextHasLetter != nil) {
        return false // return false if there's a "." in the current text and a "." thereafter
    }
    else if replacementTextHasLetter == nil || replacementTextHasDecimalSeparator != nil {
        return true
    } else {
        return false
    }

}