如何在用户输入字符和防止无效字符时测试字符输入到UITextField

时间:2012-02-18 18:56:48

标签: ios validation uitextfield user-input

首先,我为UITextField设置键盘以使用带小数形式的数字。因此用户只能输入数字和一个小数。

我想要做的是在用户输入时测试输入并防止输入多个小数,并将数字的小数部分限制为两个位置。我不想将数字四舍五入,甚至不将输入视为数字。我只想阻止用户在小数点右侧输入两位数以上。

6 个答案:

答案 0 :(得分:45)

解决方案最终证明是相当微不足道的。不幸的是,与此问题相关的许多问题和答案都是关于验证或格式化数值,而不是控制用户可以输入的内容。

shouldChangeCharactersInRange委托方法的以下实现是我的解决方案。与往常一样,正则表达式在这种情况下摇滚。 RegExLib.com是有用的RegEx样品或解决方案的绝佳来源。我不是RegEx的大师,总是在努力将它们放在一起,所以欢迎提出任何改进建议。

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

        NSString *expression = @"^([0-9]+)?(\\.([0-9]{1,2})?)?$";

        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression 
                                                                               options:NSRegularExpressionCaseInsensitive 
                                                                                 error:nil];
        NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
                                                            options:0
                                                              range:NSMakeRange(0, [newString length])];        
        if (numberOfMatches == 0)
            return NO;        
    }

    return YES;
}

以上代码允许用户输入以下类型的值:1,1.1,1.11,.1,.11。请注意,此实现不会替换文本字段的字符串,这会导致递归。如果'newString'与正则表达式不匹配,此解决方案只会拒绝用户输入的下一个字符。

答案 1 :(得分:5)

好!如果有人需要它使用非美国货币:欧元或其他分数用逗号而不是点分隔的那个使用这个:

NSString *expression = @"^([0-9]+)?([\\,\\.]([0-9]{1,2})?)?$";

唯一的区别是它允许使用逗号或点。 ([\,\。] - 或。或者)只有技巧是你需要在使用获取的数字时用点替换逗号,因为计算机使用点来分隔分数而不是逗号。

答案 2 :(得分:3)

在iOS中处理此问题的标准方法是将UITextFieldDelegate附加到UITextField,并实施textField:shouldChangeCharactersInRange:replacementString:方法。在此方法中,您可以为您的目的验证字符串是否具有正确的“形状”(一个点,点后不超过两位数等),如果输入不符合预期格式,则提供不同的字符串。

答案 3 :(得分:1)

经过多次实验并查看其他解决方案(看起来过于复杂和繁琐)后,我想出了以下内容,这可以防止用户输入任何有效货币金额。基本上,让NSNumberFormatter的一个实例(在viewController的其他地方创建)做了很多工作:

  • 1)将文本转换为数字(如果为nil,则存在无效字符,因此返回NO)
  • 2)然后将数字转换为货币
  • 3)然后将货币字符串转换回数字,如果与原始字符串不同(表示输入的小数太多),则返回NO
  • 4)然后制作一个NSDecimalNumber,这就是我想要的。当然,对你来说可能有所不同。 到目前为止对我有用 - 希望这有助于某人。

首先,我将键盘设置为UIKeyboardTypeDecimalPad。然后我使用了以下代码

  -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

NSString *textString = [textField.text stringByReplacingCharactersInRange:range withString:string];

[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *amountNumber = [numberFormatter numberFromString:textString];

if ([textString length] > 0) {
    if (!amountNumber) {
        return NO;
    }
} else {
    amountNumber = @0;
}


[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *amountStringer = [numberFormatter stringFromNumber:amountNumber];
NSNumber *amountAgain = [numberFormatter numberFromString:amountStringer];

//
//make sure that the number obtained again is the same....prevents too many decimals....
if (![amountNumber isEqualToNumber:amountAgain]) {
    return NO;
}

[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
amountShow.text = amountStringer;

self.amount = [NSDecimalNumber decimalNumberWithDecimal:[amountAgain decimalValue]];
NSLog(@"decimal Amount is %@", self.amount);

return YES;

}

答案 4 :(得分:0)

对于 Swift 4 问题的主要答案是

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard textField == quantityTextField, let textFieldString = textField.text as NSString? else {
        return true
    }

    let newString = textFieldString.replacingCharacters(in: range, with: string)
    let expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$"

    let regex = try? NSRegularExpression(pattern: expression, options: .caseInsensitive)
    let numberOfMathces = regex?.numberOfMatches(in: newString, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, newString.characters.count))

    if numberOfMathces == 0 {
        return false
    }

    return true
}

答案 5 :(得分:-1)

你可以将uitexfield的字符串传递给下面的方法,它会返回yes / no ..因此你可以显示错误

- (BOOL) validatePhone: (NSString *) aMobile {
    NSString *phoneRegex = @"^+(?:[0-9] ?){6,14}[0-9]$"; 
    NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex];
    if (aMobile.length>0) {
        NSString *mobileTextString = [[mobileText.text componentsSeparatedByCharactersInSet:
                                       [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] 
                                      componentsJoinedByString:@""];
        NSString *firstNumber = [aMobile substringToIndex:1];
       if (mobileTextString.length!=10){

            return NO;
        }

    }
        return [phoneTest evaluateWithObject:aMobile];
}