如何限制 UITextField 中的十进制输入值
How to limit decimal input value in UITextField
我目前正在检查我的 UITextField
,它设置为在 shouldChangeCharactersIn
中显示数字小键盘,以将输入限制为仅一个小数点分隔符和 2 个小数点(感谢 this question):
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let decimalSeparator = String(Locale.current.decimalSeparator ?? ".")
if (textField.text?.contains(decimalSeparator))! {
let limitDecimalPlace = 2
let decimalPlace = textField.text?.components(separatedBy: decimalSeparator).last
if (decimalPlace?.count)! < limitDecimalPlace {
return true
} else {
return false
}
}
}
效果很好。但是,现在可以插入用户想要的任何值,我想将其限制为低于 999 的值。我曾经检查长度以只允许 3 个字符,但现在我想允许以下值(例如) :
143
542.25
283.02
19.22
847.25
但我不想让:
2222
3841.11
999.99
我该怎么做?
您可能需要两次检查:
确保是xxx.xx
的形式。这种模式匹配通常通过使用正则表达式搜索来实现。
这里的技巧是确保您支持所有带小数位和不带小数位的排列,其中小数位数为两位或更少,整数位数为三位或更少。
尝试将其转换为数字并检查该值是否小于 999。
因此:
let formatter = NumberFormatter()
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let candidate = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
let separator = formatter.decimalSeparator!
if candidate == "" { return true }
let isWellFormatted = candidate.range(of: "^[0-9]{1,3}([\(separator)][0-9]{0,2})?$", options: .regularExpression) != nil
if isWellFormatted,
let value = formatter.number(from: candidate)?.doubleValue,
value >= 0,
value < 999 {
return true
}
return false
}
注:
我假设您希望用户能够遵守其设备的本地化设置(例如,让德国用户输入 123,45
,因为他们使用 ,
作为小数点分隔符).
正则表达式,如果你不习惯正则表达式,"^[0-9]{1,3}([\(separator)][0-9]{0,2})?$”
可能看起来有点毛茸茸。
^
匹配字符串的开头;
[0-9]
明显匹配任意数字;
{1,3}
匹配一到三位整数;
-
(...)?
表示“可选,查找以下内容”;
- 同样,
[0-9]{0,2}
表示“介于零和两位小数之间;和
$
匹配字符串的结尾。
我目前正在检查我的 UITextField
,它设置为在 shouldChangeCharactersIn
中显示数字小键盘,以将输入限制为仅一个小数点分隔符和 2 个小数点(感谢 this question):
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let decimalSeparator = String(Locale.current.decimalSeparator ?? ".")
if (textField.text?.contains(decimalSeparator))! {
let limitDecimalPlace = 2
let decimalPlace = textField.text?.components(separatedBy: decimalSeparator).last
if (decimalPlace?.count)! < limitDecimalPlace {
return true
} else {
return false
}
}
}
效果很好。但是,现在可以插入用户想要的任何值,我想将其限制为低于 999 的值。我曾经检查长度以只允许 3 个字符,但现在我想允许以下值(例如) :
143
542.25
283.02
19.22
847.25
但我不想让:
2222
3841.11
999.99
我该怎么做?
您可能需要两次检查:
确保是
xxx.xx
的形式。这种模式匹配通常通过使用正则表达式搜索来实现。这里的技巧是确保您支持所有带小数位和不带小数位的排列,其中小数位数为两位或更少,整数位数为三位或更少。
尝试将其转换为数字并检查该值是否小于 999。
因此:
let formatter = NumberFormatter()
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let candidate = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
let separator = formatter.decimalSeparator!
if candidate == "" { return true }
let isWellFormatted = candidate.range(of: "^[0-9]{1,3}([\(separator)][0-9]{0,2})?$", options: .regularExpression) != nil
if isWellFormatted,
let value = formatter.number(from: candidate)?.doubleValue,
value >= 0,
value < 999 {
return true
}
return false
}
注:
我假设您希望用户能够遵守其设备的本地化设置(例如,让德国用户输入
123,45
,因为他们使用,
作为小数点分隔符).正则表达式,如果你不习惯正则表达式,
"^[0-9]{1,3}([\(separator)][0-9]{0,2})?$”
可能看起来有点毛茸茸。^
匹配字符串的开头;[0-9]
明显匹配任意数字;{1,3}
匹配一到三位整数;-
(...)?
表示“可选,查找以下内容”; - 同样,
[0-9]{0,2}
表示“介于零和两位小数之间;和 $
匹配字符串的结尾。