如何限制 UITextField 中的小数点数?
Posted
技术标签:
【中文标题】如何限制 UITextField 中的小数点数?【英文标题】:How can I limit the number of decimal points in a UITextField? 【发布时间】:2012-05-01 20:43:32 【问题描述】:我有一个 UITextField,点击它会在左下角显示一个带有小数点的数字键盘。我正在尝试限制该字段,以便用户只能放置 1 个小数点
例如 2.5 确定 2..5 不行
【问题讨论】:
【参考方案1】:像这样实现 shouldChangeCharactersInRange 方法:
// Only allow one decimal point
// Example assumes ARC - Implement proper memory management if not using.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *arrayOfString = [newString componentsSeparatedByString:@"."];
if ([arrayOfString count] > 2 )
return NO;
return YES;
这会创建一个由小数点分割的字符串数组,因此如果小数点不止一个,我们将在数组中至少有 3 个元素。
【讨论】:
您可以使用 NSRegularExpression 来确定 newString 是否包含多个小数,而不是使用 componentsSeparatedByString。 真的!有很多方法可以做到这一点。我通常使用它,因为我经常想对整数和小数部分做一些不同的事情。 使用正则表达式可以更好地控制文本字段接受的字符以及它们将采用的格式。 @nizx 对于这种特定情况,我认为这并不重要,尽管您的示例更长并且对于新用户来说“看起来”更复杂。对于更复杂的例子,你可能是对的,或者如果它们是数字,那么使用 NSNumberFormatter 也可能是合适的。 而不是@"。"对于小数点分隔符,也可以从 [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]] 中获取。这样,对于使用逗号作为分隔符的区域,代码也可以正常工作。【参考方案2】:这是一个带有正则表达式的示例,该示例限制为只有一位小数和两位小数。您可以对其进行调整以满足您的需求。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = @"^[0-9]*((\\.|,)[0-9]0,2)?$";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
return numberOfMatches != 0;
【讨论】:
不错的答案。作为一个有建设性的评论家,我会建议你提高你的 RegEx 知识。诸如“([0-9]+)?”之类的东西可以用 "[0-9]*" 代替它使它更具可读性和性能。我已经对答案进行了适当的改进。 @"^-?[0-9]*((\\.|,)[0-9]0,2)?$" 也可以输入负数。 【参考方案3】:Swift 3 实现此 UITextFieldDelegate 方法以防止用户输入无效数字:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
let text = (textField.text ?? "") as NSString
let newText = text.replacingCharacters(in: range, with: string)
if let regex = try? NSRegularExpression(pattern: "^[0-9]*((\\.|,)[0-9]*)?$", options: .caseInsensitive)
return regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
return false
它使用逗号或点作为小数分隔符。您还可以使用此模式限制小数位数:"^[0-9]*((\\.|,)[0-9]0,2)?$"
(在本例中为 2)。
【讨论】:
【参考方案4】:斯威夫特 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
// Allow to remove character (Backspace)
if string == ""
return true
// Block multiple dot
if (textField.text?.contains("."))! && string == "."
return false
// Check here decimal places
if (textField.text?.contains("."))!
let limitDecimalPlace = 2
let decimalPlace = textField.text?.components(separatedBy: ".").last
if (decimalPlace?.count)! < limitDecimalPlace
return true
else
return false
return true
目标-C
//Create this variable in .h file or .m file
float _numberOfDecimal;
//assign value in viewDidLoad method
numberOfDecimal = 2;
#pragma mark - TextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// Allow to remove character (Backspace)
if ([string isEqualToString:@""])
return true;
// Block multiple dot
if ([textField.text containsString:@"."] && [string isEqualToString:@"."])
return false;
// Check here decimal places
if ([textField.text containsString:@"."])
NSString *strDecimalPlace = [[textField.text componentsSeparatedByString:@"."] lastObject];
if (strDecimalPlace.length < _numberOfDecimal)
return true;
else
return false;
return true;
【讨论】:
【参考方案5】:对于 Swift 2.3 防止用户在两位之后输入十进制数字 -
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
let decimalPlacesLimit = 2
let rangeDot = txtPrice.text!.rangeOfString(".", options: .CaseInsensitiveSearch)
if rangeDot?.count > 0
if (string == ".")
print("textField already contains a separator")
return false
else
var explodedString = txtPrice.text!.componentsSeparatedByString(".")
let decimalPart = explodedString[1]
if decimalPart.characters.count >= decimalPlacesLimit && !(string == "")
print("textField already contains \(decimalPlacesLimit) decimal places")
return false
【讨论】:
欢迎来到 Stack Overflow!虽然您可能已经解决了这个用户的问题,但纯代码的答案对于将来遇到这个问题的用户来说并不是很有帮助。请编辑您的答案以解释为什么您的代码解决了原始问题。【参考方案6】:基于公认的答案,以下方法验证了在处理货币格式时有用的三个案例:
-
数量极大
小数点后超过 2 个字符
多于 1 个小数点
确保您的文本字段的委托设置正确,您的类符合UITextField
协议,并添加以下委托方法。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// Check for deletion of the $ sign
if (range.location == 0 && [textField.text hasPrefix:@"$"])
return NO;
NSString *updatedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *stringsArray = [updatedText componentsSeparatedByString:@"."];
// Check for an absurdly large amount
if (stringsArray.count > 0)
NSString *dollarAmount = stringsArray[0];
if (dollarAmount.length > 6)
return NO;
// Check for more than 2 chars after the decimal point
if (stringsArray.count > 1)
NSString *centAmount = stringsArray[1];
if (centAmount.length > 2)
return NO;
// Check for a second decimal point
if (stringsArray.count > 2)
return NO;
return YES;
【讨论】:
有一种情况没有正确处理:如果dollarAmount已经达到6个字符,你可能还是要输入centAmount。【参考方案7】:-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
if(textField == min_textfield )
if([textField.text rangeOfString:@"."].location == NSNotFound)
if([string isEqualToString:@"."] )
flag_for_text = 1;
else
textField.text = [NSMutableString stringWithFormat:@"%@",textField.text];
else
if([string isEqualToString:@"."])
return NO;
else
textField.text = [NSMutableString stringWithFormat:@"%@",textField.text];
【讨论】:
【参考方案8】:试试这个:-
public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
if(text == "," || text == "." )
let countdots = textView.text!.componentsSeparatedByString(".").count - 1
if countdots > 0 && (text == "." || text == "," )
return false
return true
【讨论】:
text
可以是多个字符,所以不能这样检查。【参考方案9】:
斯威夫特 3
无需创建数组和检查计数。限制用户只能像这样放置 1 个小数点。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
if (textField.text?.contains("."))! && string.contains(".")
return false
else
return true
【讨论】:
【参考方案10】:斯威夫特 4
最大整数个数为 4 即 9999,最大小数位数限制为 2。因此,最大数字可以是 9999.99
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
// 100 is the tag value of our textfield
/*or you may use "if textfield == myTextField" if you have an IBOutlet to that textfield */
if textField.tag == 100
//max length limit of text is 8
if textField.text!.count > 8 && string != ""
return false
let maxLength = 8
let currentString: NSString = textField.text! as NSString
// 使用下面的代码 如果您在该文本字段中输入价格并希望在用户开始在该文本字段中输入时自动插入 $,或者您可以在开头放置一些其他字符而不是 $。否则注释下面3行if条件代码
if currentString.length == 0
priceTextField.text = "$"
//插入新输入的字符后的新字符串
let newString: NSString =
currentString.replacingCharacters(in: range, with: string) as NSString
if newString.length > maxLength
return false
if (textField.text!.range(of: ".") != nil)
let numStr = newString.components(separatedBy: ".")
if numStr.count>1
let decStr = numStr[1]
if decStr.length > 2
return false
var priceStr: String = newString as String
if (textField.text!.range(of: "$") != nil)
priceStr = priceStr.replacingOccurrences(of: "$", with: "")
let price: Double = Double(priceStr) ?? 0
if price > 9999.99
return false
switch string
case "0","1","2","3","4","5","6","7","8","9":
return true
case ".":
let array = Array(textField.text!)
var decimalCount = 0
for character in array
if character == "."
decimalCount = decimalCount + 1
if decimalCount == 1
return false
else
return true
default:
let array = Array(string)
if array.count == 0
return true
return false
return true
【讨论】:
【参考方案11】:在您将 UITextField 的委托设置为的任何对象中,添加一个响应 "[- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string]
" 的方法。
然后您可以使用NSNumberFormatter
对象,或者您可以对已经存在的小数位标记进行暴力检查(如果小数点已存在则返回NO
)。
【讨论】:
【参考方案12】:简而言之,数字格式如下[NSString stringWithFormat:@"%9.5f", x];
其中5是“,”后面的小数。
【讨论】:
【参考方案13】:我制定了解决方案,让您可以控制小数位数,因此用户只能输入一个小数分隔符,您还可以控制小数位数。
只需正确设置 decimalPlacesLimit 值即可。
看方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
NSLog(@"text on the way: %@", string);
NSUInteger decimalPlacesLimit = 2;
NSRange rangeDot = [textField.text rangeOfString:@"." options:NSCaseInsensitiveSearch];
NSRange rangeComma = [textField.text rangeOfString:@"," options:NSCaseInsensitiveSearch];
if (rangeDot.length > 0 || rangeComma.length > 0)
if([string isEqualToString:@"."])
NSLog(@"textField already contains a separator");
return NO;
else
NSArray *explodedString = [textField.text componentsSeparatedByString:@"."];
NSString *decimalPart = explodedString[1];
if (decimalPart.length >= decimalPlacesLimit && ![string isEqualToString:@""])
NSLog(@"textField already contains %d decimal places", decimalPlacesLimit);
return NO;
return YES;
【讨论】:
【参考方案14】:斯威夫特 4
在 UITextField 中避免多个小数点(. 或 ,)的有效且简单的方法:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
if(string == "," || string == "." )
if ((textField.text?.contains(","))! || (textField.text?.contains("."))!)
return false
return true
【讨论】:
【参考方案15】:-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
if([string isEqualToString:@"."])
BOOL containsDecimal = [textField.text containsString:@"."];
return !containsDecimal;
return YES;
如果文本字段文本已经包含一个 '.'然后返回 NO 否则返回 YES。
【讨论】:
【参考方案16】:SWIFT 5
改进
信息:不允许:
开头的分隔符 在开头加上另一个数字,除非您在后面添加分隔符1:设置键盘类型为:小数点
2:复制过去
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
//!\ set the keyboard type to : Decimal Pad /!\\
// CUSTOM SETUP
let c = NSLocale.current.decimalSeparator ?? "."
let limitBeforeSeparator = 2
let limitAfterSeparator = 2
// ---------
var validatorUserInput:Bool = false
let text = (textField.text ?? "") as NSString
let newText = text.replacingCharacters(in: range, with: string)
// Validator
let pattern = "(?!0[0-9])\\d*(?!\\\(c))^[0-9]0,\(limitBeforeSeparator)((\\\(c))[0-9]0,\(limitAfterSeparator))?$"
if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
validatorUserInput = regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
if validatorUserInput
// setting data or something eles before the return
if let char = string.cString(using: String.Encoding.utf8)
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92 && textField.text?.count == 1)
print("Backspace was pressed")
print(newText)
// do something...
else
print("Number Added")
print(newText)
// do something...
return validatorUserInput
else
return validatorUserInput
3:方法中设置,如果要x分隔符前后最大位数
let limitBeforeSeparator = 2
let limitAfterSeparator = 2
【讨论】:
以上是关于如何限制 UITextField 中的小数点数?的主要内容,如果未能解决你的问题,请参考以下文章
UITextField 限制输入金额(项目中遇到判断输入金额)