3

我想限制允许用户输入的小数位数UITextField,只接受(本地化)数字输入。

允许 4 个小数位的示例:

  • 好:42,,,10.12312345.2345
  • 坏:0.1234566.54321

现在,我在委托中使用NSNumberFormatter's来确定它是否是合法的数值。numberFromString:UITextFieldtextField:shouldChangeCharactersInRange:replacementString:

不幸的是,NSNumberFormatter似乎忽略maximumFractionDigitsnumberFromString:. 在使用我的测试中,getObjectValue:forString:range:error:我遇到了同样的问题,range之后也是字符串的全长(除非我开始输入字母;然后range只用数字表示字符串的一部分):

NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 3;
formatter.roundingMode = NSNumberFormatterRoundHalfUp;
formatter.generatesDecimalNumbers = YES;
NSDecimalNumber* n = (NSDecimalNumber*)[formatter numberFromString:@"10.12345"];
NSLog(@"Number: %@", n.description); // expected: 10.123, but is: 10.12345

如何最好地限制用户输入中的小数位数?

4

3 回答 3

1

有几种方法可以做到这一点,但最简单的可能是将字符串分成两部分(您必须本地化 '.')并检查第二部分的长度,如下所示:

- (BOOL)LNNumberIsValid:(NSString *)string
{
    NSArray *numArray = [string componentsSeparatedByString:@"."];
    if ([numArray count] == 2)
        if ([[numArray objectAtIndex:1] length] > 4)
            return NO;

    return YES;
}

// Tests
NSLog(@"42: %i", [self LNNumberIsValid:@"42"]); // 1
NSLog(@"10.123: %i", [self LNNumberIsValid:@"10.123"]); // 1
NSLog(@"12345.2345: %i", [self LNNumberIsValid:@"12345.2345"]); // 1

NSLog(@"0.123456: %i", [self LNNumberIsValid:@"0.123456"]); // 0
NSLog(@"6.54321: %i", [self LNNumberIsValid:@"6.54321"]); // 0

编辑:
您添加到问题的代码的问题是您正在打印descriptionNSDecimalNumber,它没有本地化或限制为位数。NSDecimalNumber 本身存储您提供的所有内容,因此如果您想更改原始字符串(如我上面的示例),则需要更改它。但是,一旦有了 NSDecimalNumber,就可以使用相同的数字格式化程序将其转换回您喜欢的格式的字符串:

NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 3;
formatter.roundingMode = NSNumberFormatterRoundHalfUp;
formatter.generatesDecimalNumbers = YES;
NSDecimalNumber* n = (NSDecimalNumber*)[formatter numberFromString:@"10.12345"];
NSString *s = [formatter stringFromNumber:n];
NSLog(@"Number: %@", s); // expected: 10.123, and is: 10.123
于 2013-08-19T21:52:45.410 回答
1

获得不受限制的数字后,您可以在该数字上使用 stringWithFormat 来创建具有一定小数位数的字符串。

例如。

double number = myTextField.text.doubleValue;
NSString *restrictedString =  [NSString stringWithFormat:@"%.4f", number];
于 2013-08-19T21:56:12.830 回答
0

我解决这个问题的方法是检查小数点分隔符的位置,并确保插入在该位置之前,或者插入不会超过最大小数位数。此外,我检查新分隔符的输入是否不会出现在会导致超过允许的小数位数的地方,并且不能插入超过一个分隔符

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *separator = self.numberFormatter.decimalSeparator;

if(string.length == 0) {
    // Empty String means deletion, always possible
    return YES;
}

// Check for valid characters (0123456789 + decimal Separator)
for (int i = 0; i < [string length]; ++i) {
    unichar c = [string characterAtIndex:i];
    if (![self.legalCharSet characterIsMember:c])
    {
        return NO;
    }
}

// Checks if input is separator
if([string isEqualToString:separator]) {
    // Check that separator insertion would not lead to more than 2 fraction digits and that not more than one separators are inserted
// (the MIN() makes sure that length - kMaxFractionDigits won’t be below 0 as length and location are NSUIntegers)
    return range.location >= self.valueField.text.length - MIN(self.valueField.text.length,kMaxFractionDigits) && [self.valueField.text containsString:separator] == NO;
} else {
    // Check if a separator is already included in the string
    NSRange separatorPos = [self.valueField.text rangeOfString: separator];
    if(separatorPos.location != NSNotFound) {
        // Make sure that either the input is before the decimal separator or that the fraction digits would not exceed the maximum fraction digits.
        NSInteger fractionDigits = self.valueField.text.length - (separatorPos.location + 1);
        return fractionDigits + string.length <= kMaxFractionDigits || range.location <= separatorPos.location;
    }
}

return YES;
}

该方法可能不是防弹的,但对于常见的文本插入应该足够了。

于 2017-05-06T15:53:24.713 回答