无法从 UITextField 中删除所有字符

Cannot delete all characters from a UITextField

在我的应用程序中,可以添加交易。该交易有一个名为 amount 的属性,这个属性是一个 Double。我已经实现了添加负数和正数的功能。我用 UISegmentedControll 来做到这一点。如果用户将金额设为负数,amountTextField.text 将变为“-”+ amountTextField.text。用户可以输入双打我添加了这个功能:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let oldText = textField.text, let r = Range(range, in: oldText) else{
            return true
        }
        let newText = oldText.replacingCharacters(in: r, with: string)
        let isNumeric = newText.isEmpty || (Double(newText) != nil)
        let numberOfDots = newText.components(separatedBy: ".").count - 1

        let numberOfDecimalDigits: Int
        if let dotIndex = newText.index(of: "."){
            numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
        } else {
            numberOfDecimalDigits = 0
        }
        return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2
    }

当正数Double前面有减号时,无法删除字符串的第一个数字。例如,如果 amountTextField.text 是 -399.99,并且用户按他想要的次数按删除按钮,textField 将显示 -3。在我的调试工作中,我发现我在代码中添加的功能是造成这种情况的原因。

我该如何解决这个问题?

这是一种方法:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let oldText = textField.text, let r = Range(range, in: oldText) else {
        return true
    }

    let newText = oldText.replacingCharacters(in: r, with: string)

    if newText == "-" {
        // result will be "-" so just
        return true
    }

    let isNumeric = newText.isEmpty || (Double(newText) != nil)
    let numberOfDots = newText.components(separatedBy: ".").count - 1

    let numberOfDecimalDigits: Int
    if let dotIndex = newText.index(of: "."){
        numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
    } else {
        numberOfDecimalDigits = 0
    }


    if isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2 {
        // value passes those tests, so make sure the leading "-" is still there
        // if not, prepend it, set the text and return false
        if newText.first != "-" {
            textField.text = "-" + newText
            return false
        }
    }

    return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2
}

我们还有几个额外的 if 块要处理:

  • 用户移动插入点以删除“-”
  • 用户执行 "select all" 并点击一个新数字或删除,或粘贴一个值

我希望您已经知道,如果分段控件 not 处于负位置,您还需要布尔检查以不同方式处理此问题。