自定义百分比字段 UiTextField
custom percentage field UiTextField
我有一个文本字段委托方法,我的用例是:-
如果 (.) 点不存在限制输入两个字符,因为 100% 不应该打折。
如果用户输入的是 1.99,如何更新委托方法使其在 (.)
后取两个数字
相同,如果输入是 12.99 如何更新委托方法,它应该在 (.)
之后取两个数字
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard !string.isEmpty else {
return true
}
// maximum limit of input 2 as 100% should not be discount.
if !textField.text!.contains(".") {
let maxLength = 2
let currentString: NSString = (textField.text ?? "") as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
} else {
// if there is (.)
let maxLength = 3
let currentString: NSString = (textField.text ?? "") as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
}
}
这就是答案
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard !string.isEmpty else {
return true
}
let newText = (textField.text! as NSString).replacingCharacters(in: range, with: string) as String
if let num = Double(newText), num >= -1 && num <= 100 {
return true
} else {
return false
}
}
一种选择是跟踪小数点前后的位数,并确定您是否已达到阈值。
您的回答没有任何问题,但如果您愿意,这里还有一个替代选项。您可以使用正则表达式,因为有时会跟踪多个布尔值、计数、变量可能有一些边缘情况。
我的 REGEX 技能不是太强,但这里有一个 nice SO thread 可以为您的问题获取一个 REGEX,您可能能够比我在下面使用的 REGEX 优化得更好。
private func isValidDecimal(_ text: String) -> Bool {
// ^ $ - Anchors to analyze the text as one chunk / block
// \d{1,2}) - Match a string that has 1 or 2 characters
// | - OR
// \d{1,2}\.{1}(\d{1,2})?
// - \d{1,2} - Match a string that has 1 or 2 characters
// - \.{1} - followed by a max of 1 decimal
// - (\d{1,2})? - followed by 0 - 2 characters after the decimal
let pattern = "^(\d{1,2}\.{1}(\d{1,2})?|\d{1,2})$"
do
{
let regex = try NSRegularExpression(pattern: pattern)
let matches = regex.matches(in: text,
options: NSRegularExpression.MatchingOptions(),
range: NSRange(location: 0,
length: text.count))
// We only want 1 match as more than one match
// would mean error
return matches.count == 1
}
catch
{
// handle errors
print("error")
}
return false
}
extension TextHighlightVC: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
guard let text = textField.text else { return false }
return isValidDecimal(text + string)
}
}
请注意,这可能不是最佳的 REGEX 模式,它只是向您展示一个选项。
这是似乎适用于所有用例的结果
根据 Omar 的评论更新:
one question if I press .5 at starting, textfield should show 0.5 how
to achieve this using same regex
我认为我们可以将其作为 edge
案例处理,而不是使用正则表达式来处理,因为这对我来说似乎更容易。
我们检查输入的第一个字符是否为小数,然后添加 0。
这是我会做的:
extension TextHighlightVC: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
guard let text = textField.text else { return false }
// Check if the first character entered is a decimal
if text.count == 0 && string == "." {
// Add 0 to the text field
textField.text = "0"
return true
}
return isValidDecimal(text + string)
}
}
我有一个文本字段委托方法,我的用例是:-
如果 (.) 点不存在限制输入两个字符,因为 100% 不应该打折。
如果用户输入的是 1.99,如何更新委托方法使其在 (.)
后取两个数字相同,如果输入是 12.99 如何更新委托方法,它应该在 (.)
之后取两个数字
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard !string.isEmpty else {
return true
}
// maximum limit of input 2 as 100% should not be discount.
if !textField.text!.contains(".") {
let maxLength = 2
let currentString: NSString = (textField.text ?? "") as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
} else {
// if there is (.)
let maxLength = 3
let currentString: NSString = (textField.text ?? "") as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
}
}
这就是答案
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard !string.isEmpty else {
return true
}
let newText = (textField.text! as NSString).replacingCharacters(in: range, with: string) as String
if let num = Double(newText), num >= -1 && num <= 100 {
return true
} else {
return false
}
}
一种选择是跟踪小数点前后的位数,并确定您是否已达到阈值。
您的回答没有任何问题,但如果您愿意,这里还有一个替代选项。您可以使用正则表达式,因为有时会跟踪多个布尔值、计数、变量可能有一些边缘情况。
我的 REGEX 技能不是太强,但这里有一个 nice SO thread 可以为您的问题获取一个 REGEX,您可能能够比我在下面使用的 REGEX 优化得更好。
private func isValidDecimal(_ text: String) -> Bool {
// ^ $ - Anchors to analyze the text as one chunk / block
// \d{1,2}) - Match a string that has 1 or 2 characters
// | - OR
// \d{1,2}\.{1}(\d{1,2})?
// - \d{1,2} - Match a string that has 1 or 2 characters
// - \.{1} - followed by a max of 1 decimal
// - (\d{1,2})? - followed by 0 - 2 characters after the decimal
let pattern = "^(\d{1,2}\.{1}(\d{1,2})?|\d{1,2})$"
do
{
let regex = try NSRegularExpression(pattern: pattern)
let matches = regex.matches(in: text,
options: NSRegularExpression.MatchingOptions(),
range: NSRange(location: 0,
length: text.count))
// We only want 1 match as more than one match
// would mean error
return matches.count == 1
}
catch
{
// handle errors
print("error")
}
return false
}
extension TextHighlightVC: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
guard let text = textField.text else { return false }
return isValidDecimal(text + string)
}
}
请注意,这可能不是最佳的 REGEX 模式,它只是向您展示一个选项。
这是似乎适用于所有用例的结果
根据 Omar 的评论更新:
one question if I press .5 at starting, textfield should show 0.5 how to achieve this using same regex
我认为我们可以将其作为 edge
案例处理,而不是使用正则表达式来处理,因为这对我来说似乎更容易。
我们检查输入的第一个字符是否为小数,然后添加 0。
这是我会做的:
extension TextHighlightVC: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
guard let text = textField.text else { return false }
// Check if the first character entered is a decimal
if text.count == 0 && string == "." {
// Add 0 to the text field
textField.text = "0"
return true
}
return isValidDecimal(text + string)
}
}