【问题标题】:Limit UITextField to one decimal point Swift将 UITextField 限制为小数点后一位 Swift
【发布时间】:2014-10-03 06:08:38
【问题描述】:

如何使用 Swift 将 UITextField 限制为小数点后一位?文本字段用于输入价格,因此我不能允许超过一位小数。如果我使用的是 Objective-C,我会使用以下代码:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSArray *sep = [newString componentsSeparatedByString:@"."];
    if([sep count] >= 2)
    {
        NSString *sepStr=[NSString stringWithFormat:@"%@",[sep objectAtIndex:1]];
        return !([sepStr length]>1);
    }
    return YES;
}

但由于 Swift 使用范围的方式不同,我无法将此代码转换为 Swift。第一行给我一个错误说NSRange is not convertible to Range<String.Index>

编辑:在看到答案之前,我最终这样做了:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    let tempRange = textField.text.rangeOfString(".", options: NSStringCompareOptions.LiteralSearch, range: nil, locale: nil)
    if tempRange?.isEmpty == false && string == "." {
        return false
    }

    return true
}

我在另一个帖子上发现了这个。该解决方案效果很好,但我不确定这是否是最好的方法,但它是一种简短而干净的方法。

【问题讨论】:

  • 我已经尝试过实现这个功能,但我不知道如何在每次按键时调用它。如果我尝试将 NSRange 作为 NSRange 的参数,我会看到错误。我可以看看你是如何让这个函数在每次按键时调用的实现吗?

标签: ios objective-c swift uitextfield


【解决方案1】:
// decimal points limit on numbers text fields
    @objc static func canEnterDigits(upTo decimalPoint: Int, text: String) -> Bool {
        
        if self.isNumber(text) || text == "" {
            
            let stringArr: [String] = text.components(separatedBy: ".")
            if stringArr.count >= 2 {
                let sepString = stringArr[1]
                if sepString.count > decimalPoint {
                    return false
                }
            }
            
            return true
            
        } else {
            return false
        }
    }


static func isNumber(_ value: String?) -> Bool {
        let nf = NumberFormatter()
        let isDecimal = nf.number(from: value ?? "") != nil
        return isDecimal
    }

【讨论】:

    【解决方案2】:

    我不确定性能,但这是迄今为止最简单的解决方案。

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if let text = textField.text {
            // Allow only one dot character in the text field
            if text.contains(".") && string == "." {
                return false
            }
        }
    }
    

    【讨论】:

      【解决方案3】:
      func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
                  if (textField.text?.componentsSeparatedByString(".").count > 1 && string == ".")
                  {
                      return false
                  }
                  return string == "" || (string == "." || Float(string) != nil)
          }
      

      【讨论】:

        【解决方案4】:

        Swift 4、Xcode 9.2

        这将删除最后输入的小数点:

        let numberOfDecimalPoints = textField.text.components(separatedBy: ".").count - 1
        
        if numberOfDecimalPoints > 1 {
            textField.deleteBackward()
        }
        

        【讨论】:

          【解决方案5】:

          希望对你有帮助:

          func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 
          
           let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) 
          
           let stringArr: [String] =   newString.components(separatedBy: ".")
          
          if stringArr.count < 2 || (stringArr.count == 2 && stringArr[1].count == 1){ 
               return true
          
            } 
           return false
            }
          

          【讨论】:

            【解决方案6】:

            Swift 4 和 Xcode 9.2

            此解决方案只允许输入一个小数点,因此允许输入有效的双精度数。

            // Only allows one decimal point
            func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            
                let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
                let arrayOfString = newString.components(separatedBy: ".")
            
                if arrayOfString.count > 2 {
                    return false
                }
                return true
            }
            

            【讨论】:

              【解决方案7】:

              试试这个输入一位小数:-

              func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
              
              
                  if(string == "." ){
                      let countdots = textField.text!.componentsSeparatedByString(".").count - 1
              
                      if countdots > 0 && string == "."
                      {
                          return false
                      }
                  }
                  return true
              
              }
              

              【讨论】:

                【解决方案8】:

                我建议使用 NSNumberFormatter 的 decimalSeparator 属性来分割你的字符串。以下是仅使用 NSNumberFormatter 将输入限制为小数点后一位的方法:

                func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
                
                    if string.isEmpty { // back key
                        return true
                    }
                
                    if let input = textField.text {
                        let numberFormatter = NSNumberFormatter()
                        let range = input.rangeOfString(numberFormatter.decimalSeparator)
                        if let r = range {
                            let endIndex = input.startIndex.advancedBy(input.startIndex.distanceTo(r.endIndex))
                            let decimals = input.substringFromIndex(endIndex)
                            return decimals.characters.count < 1
                        }
                    }
                
                    return true
                }
                

                【讨论】:

                  【解决方案9】:

                  Alexey 在我之前到达那里,但是看到我已经实现了一个 Swift 版本来检查事情,这里是:

                  func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
                  
                      // I'm explicitly unwrapping newString here, as I want to use reverse() on it, and that
                      // apparently doesn't work with implicitly unwrapped Strings.
                      if let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string) {
                  
                          var decimalFound = false
                          var charactersAfterDecimal = 0
                  
                          for ch in reverse(newString) {
                              if ch == "." {
                                  decimalFound = true
                                  break
                              }
                              charactersAfterDecimal++
                          }
                          if decimalFound && charactersAfterDecimal > 1 {
                              return false
                          }
                      }
                      return true;
                  }
                  

                  请注意,第一行现在将 textField.text 显式转换为 NSString。这是因为 stringByReplacingCharactersInRange 的 String 版本采用 Swift 范围,而不是传入的 NSRange。

                  我还使后面的代码更加 Swiftian,删除了 NSString 操作。 (我不相信这是非常有效的,因为 reverse(String) 实际上可能会反转整个 String 而不是提供简单的反向迭代器,但它看起来是最 Swifty 的方式。)

                  【讨论】:

                  • 谢谢,你能检查我对原始问题的编辑吗?这是一个好方法吗?我不敢相信我没有考虑将其转换为 NSString。那些深夜的编码课程有时会让你忘记基础知识。
                  • 我试过这段代码,但它允许我输入任意数量的“.”。我实际上想限制“。”的数量。为 1 并且还限制“。”之后的位数。到 2. 我正在考虑将您的代码与我编辑的问题中的代码结合起来以使其工作。
                  【解决方案10】:

                  您在 Swift 中的第一行将如下所示:

                  var newString = NSString(string: textField.text).stringByReplacingCharactersInRange(range, withString: string)
                  

                  【讨论】:

                  • 是的。或(textField.text as NSString).stringByReplacingCharacters...。基本上大部分 API 仍然使用 NSString 是可以理解的,它具有 NSRange 范围,它们是相同的概念,但与 Swift String 范围不兼容。阅读Strings in Swift 可能有助于理清思路;顺便提了一下,但整篇文章对于理解 Swift 字符串很有帮助。
                  • 谢谢,你能检查我对原始问题的编辑吗?这是一个好方法吗?我不敢相信我没有考虑将其转换为 NSString。那些深夜的编码课程有时会让你忘记基础知识。
                  • @Shan 如果我在您的问题中使用更新后的代码,我似乎可以在小数点后输入大量数字。啊哈!你只是说你想限制文本字段中“.”的数量吗?您的原始代码限制了小数*位*的数量——它不会让你输入“0.00”,例如,只能输入“0.0”——这是一个非常不同的要求。所以,是的,如果你只想限制小数点字符的数量,你的新代码应该没问题,但它和你原来的代码不一样。
                  • @MattGibson 我实际上没有注意到这一点。谢谢你抓住那个。我会尝试使用您建议的方法。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-01-11
                  • 2021-04-23
                  • 2023-01-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-01-28
                  • 1970-01-01
                  相关资源
                  最近更新 更多