如何在UITextField中仅输入数字并限制最大长度?

10
在UITextField中,我们只输入数字,并将其限制为最多3个数字,我使用了以下代码。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string  {


    NSUInteger newLength = [textField.text length] + [string length] - range.length;

    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];

    NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];

    while (newLength < CHARACTER_LIMIT) {
        return [string isEqualToString:filtered];
    }

/* Limits the no of characters to be enter in text field */

    return (newLength > CHARACTER_LIMIT ) ? NO : YES; 

}

当我长按文本框(如下图所示),在两个数字之间输入字符串时,它允许所有特殊字符和字符。 enter image description here

可以使用正则表达式来实现这个功能。 - Rama Rao
这个答案可能有所帮助:http://stackoverflow.com/a/8370624/927947。可能是重复问题。 - NJones
5个回答

41

并不是说我不喜欢我在这个问题上写的答案,那个答案也被复制粘贴到这里了。我会尝试解释你的错误。

这个答案基于这样一个假设:你的常量定义大概长成这样:

#define NUMBERS_ONLY @"1234567890"
#define CHARACTER_LIMIT 3
你的逻辑失败的原因是你从未处理当newLength等于CHARACTER_LIMIT时的事件。
比如说,假设你的文本框为空,你请求将字符串@"ABC"粘贴到文本框中,那么你的代理方法就会被调用。你创建了一个字符串filtered,它正确地计算为空字符串,你迫不及待地想要执行return [string isEqualToString:filtered];这一行,但实际上你从来没有评估过那一行,因为你不符合while循环的入口条件,因为newLength等于3。所以简单的return (newLength > CHARACTER_LIMIT ) ? NO : YES;决定了返回值。
如果你的CHARACTER_LIMIT是4,只需想象@"ABCD"作为字符串,逻辑仍然适用。
下面是一个简单的例子,演示了你的函数修正后的工作方式。同样地,我假设CHARACTER_LIMIT等于3。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string  {
    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
    NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));
}

你可以使用 [NSCharacterSet decimalDigitCharacterSet] 替代吗? - Rhythmic Fistman

5
 -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    // Check for non-numeric characters
    NSUInteger lengthOfString = string.length;
    for (NSInteger loopIndex = 0; loopIndex < lengthOfString; loopIndex++) {
        unichar character = [string characterAtIndex:loopIndex];
        if (character < 48) return NO; // 48 unichar for 0
        if (character > 57) return NO; // 57 unichar for 9
    }
    // Check for total length
    NSUInteger proposedNewLength = textField.text.length - range.length + string.length;
    if (proposedNewLength > 3) return NO;
    return YES;
    }

对我来说它工作得很好,您可以使用此代码


1
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSString *s = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^\\d{0,3}$" options:0 error:nil];
    NSTextCheckingResult *match = [regex firstMatchInString:s options:0 range:NSMakeRange(0, [s length])];
    return (match != nil);
}

0

请查看 UITextFieldDelegate 方法

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

每次您键入/点击字符或按下剪切/粘贴之后,此方法将被调用,并在该操作改变显示的字符之前执行。在这里,您可以很好地检查maxLength和仅限数字的文本输入(使用下面给出的正则表达式模式),并根据结果返回YES或NO。如果返回YES,则会进行更改,否则不会。希望这能解决您的疑问。

0

我更喜欢使用NSNumberFormatter来验证文本是否可以解析为数字。如果字符串无法转换为数字,NSNumberFormatter将返回nil。这使您可以对输入做出反应(例如使文本变红,弹出警报)

NSNumber* value = nil;
NSNumberFormatter* format = [[NSNumberFormatter alloc] init];
value  = [format numberFromString:someValueString];//returns and
if (value == nil){
    //do something useful i.e. show alert
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接