【问题标题】:How can I limit the number of decimal points in a UITextField?如何限制 UITextField 中的小数点数?
【发布时间】:2012-05-01 20:43:32
【问题描述】:

我有一个 UITextField,点击它会在左下角显示一个带有小数点的数字键盘。我正在尝试限制该字段,以便用户只能放置 1 个小数点

例如
2.5 确定
2..5 不行

【问题讨论】:

    标签: ios uitextfield decimal-point


    【解决方案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】:

        基于公认的答案,以下方法验证了在处理货币格式时有用的三个案例:

        1. 数量极大
        2. 小数点后超过 2 个字符
        3. 多于 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
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2014-10-03
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2010-10-22
                          • 1970-01-01
                          • 2021-04-23
                          • 1970-01-01
                          相关资源
                          最近更新 更多