将UITextField限制为一个小数点Swift

时间:2014-08-10 05:41:08

标签: ios objective-c swift uitextfield

如何使用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
}

我在另一篇文章中发现了这一点。这个解决方案工作正常,但我不确定这是否是最好的方法,但它是一个简短而干净的方式。

9 个答案:

答案 0 :(得分:4)

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而不是提供一个简单的后向迭代器,但它看起来是最常用的方式。)

答案 1 :(得分:1)

你在Swift的第一行看起来像:

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

答案 2 :(得分:0)

我建议使用NSNumberFormatter的decimalSeparator属性来拆分String。以下是仅使用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
}

答案 3 :(得分:0)

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 :(得分:0)

尝试使用一个十进制条目: -

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

}

答案 5 :(得分:0)

Swift 4&amp; 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
}

答案 6 :(得分:0)

我希望它可以帮到你:

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
  }

答案 7 :(得分:0)

Swift 4,Xcode 9.2

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

let numberOfDecimalPoints = textField.text.components(separatedBy: ".").count - 1

if numberOfDecimalPoints > 1 {
    textField.deleteBackward()
}

答案 8 :(得分:0)

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

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
        }
    }
}