My Bronze Solution, feedback welcome

Here’s my contribution, I think this one works pretty well. You can insert a negative at the start even with a number already in place. You can cut and paste. Good times. I’m new to Swift though, so please give tips and feedback if you have any.

    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        
        print("Current text: \(textField.text)")
        print("Replacement text: \(string)")
        print("Index: \(range.location)")
        
        // My try at the Chapter 4 Bronze Challenge
        var checkValidString: String = textField.text!

        checkValidString.insert(contentsOf: string.characters, 
                                at: checkValidString.index(checkValidString.startIndex, offsetBy: range.location))
        
        let checkValidDouble: Double? = Double(checkValidString)
        
        if checkValidDouble == nil, string != "", checkValidString != ".", checkValidString != "+",
            checkValidString != "-", checkValidString != "-.", checkValidString != "+." {
            return false
        } else {
            return true
        }
    }

Updated this to use numberFormatter, which we learn about in Chapter 7. This solution is much better, because it adapts to different number formatting based on the device region.

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
    
    let currentLocale = Locale.current
    let decimalSeparator = currentLocale.decimalSeparator ?? "."
    
    print("Current text: \(String(describing: textField.text))")
    print("Replacement text: \(string)")
    print("Index: \(range.location)")
    print("DecimalSeparator: \(decimalSeparator)")
    
    // SECOND TRY AT BRONZE CHALLENGE, this one works great!
    var checkValidString: String = textField.text!

    checkValidString.insert(contentsOf: string.characters,
                            at: checkValidString.index(checkValidString.startIndex, offsetBy: range.location))
    
    let checkValidNumber = numberFormatter.number(from: checkValidString)
    
    if checkValidNumber == nil, string != "", checkValidString != decimalSeparator,
        checkValidString != "-", checkValidString != "-\(decimalSeparator)" {
        return false
    } else {
        return true
    }
}

Without seeing the code, those two variable names (checkValidString and checkValidNumber) sound like function names. It is important that you use informative names to denote things in your code.

Good point, I suppose using a verb in the name implies a function. To get an idea of better naming conventions, what would you suggest instead for those variable names?

I don’t know about the context, but I would suggest at least the following change.

// checkValidString -> someInputString
// checkValidNumber -> someNumber

// where the prefix some will be context dependent