如何在UITextfield中放入小数点,不应删除

时间:2016-02-09 14:42:28

标签: objective-c uitextfield string-formatting

在我的项目中,我们要求用户需要在文本字段中输入金额,文本字段最初应为0.00,并且用户必须输入值。数字应该从右向左移动,小数点应该始终存在。 就像用户输入1一样,它应该是0.01,如果用户输入112,它应该显示为1.12。

我可以在文本框字段中应用逗号,但我确实坚持小数点要求。我无法在文本框中输入小数点。有人可以帮我吗?

- (BOOL)textInput:(id <UITextInput>)textInput shouldChangeCharactersInRange:(NSRange)range withString:(NSString *)string {

      UITextField *textField = (UITextField *)textInput;

    if (textField.text.length >= MAX_LENGTH && range.length == 0)
    {
        return NO; // return NO to not change text
    }
    if (([string isEqualToString:@"0"] || [string isEqualToString:@""]) && [textField.text rangeOfString:@"."].location < range.location) {
        return YES;
    }

    // First check whether the replacement string's numeric...
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
    NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    bool isNumeric = [string isEqualToString:filtered];

    // Then if the replacement string's numeric, or if it's
    // a backspace, or if it's a decimal point and the text
    // field doesn't already contain a decimal point,
    // reformat the new complete number using
    // NSNumberFormatterDecimalStyle
    if (isNumeric ||
        [string isEqualToString:@""] ||
        ([string isEqualToString:@"."] &&
         [textField.text rangeOfString:@"."].location == NSNotFound)) {

            // Create the decimal style formatter
            NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
            [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
            [formatter setCurrencyCode:@"USD"];
            [formatter setMaximumFractionDigits:2];

            // Combine the new text with the old; then remove any
            // commas from the textField before formatting
            NSString *combinedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
            NSString *numberWithoutCommas = [combinedText stringByReplacingOccurrencesOfString:@"," withString:@""];
            NSNumber *number = [formatter numberFromString:numberWithoutCommas];

            NSString *formattedString = [formatter stringFromNumber:number];

            // If the last entry was a decimal or a zero after a decimal,
            // re-add it here because the formatter will naturally remove
            // it.
            if ([string isEqualToString:@"."] &&
                range.location == textField.text.length) {
                formattedString = [formattedString stringByAppendingString:@"."];
            }

            textField.text = formattedString;

        }

    // Return no, because either the replacement string is not
    // valid or it is and the textfield has already been updated
    // accordingly
    return NO;

}

2 个答案:

答案 0 :(得分:1)

demo

这是一种不同的方法。不要实现委托方法textField: shouldChangeCharactersInRange:withString:。而是将文本字段的“编辑已更改”事件连接到视图控制器中的操作。在操作中,我们将做两件事:根据您的要求重新格式化文本,并在重新格式化过程中保留光标位置。在重新格式化之前,我们计算从文本末尾到光标位置的偏移量。重新格式化后,我们根据该偏移重置光标位置:

- (IBAction)textFieldEditingChanged:(UITextField *)textField {
    int offset = [textField offsetFromPosition:textField.endOfDocument toPosition:textField.selectedTextRange.end];

    textField.text = textField.text.Nitya_reformattedString;

    UITextPosition *position = [textField positionFromPosition:textField.endOfDocument offset:offset];
    textField.selectedTextRange = [textField textRangeFromPosition:position toPosition:position];
}

要初始化文本字段,我们可以重新格式化空字符串:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.textField.text = @"".Nitya_reformattedString;
}

要进行重新格式化,我们会在NSString上编写一个类别:

@interface NSString (Nitya)
- (NSString *)Nitya_reformattedString;
- (BOOL)Nitya_isDigit;
@end

@implementation NSString (Nitya)

- (NSString *)Nitya_reformattedString {

请注意,文字字段会在更新其文本后发送“已修改 ,因此文字可能包含非数字字符或实际上包含任何内容,因为用户可能已选择整个内容并粘贴其他一些字符串。所以第一步就是抛弃所有非数字字符:

    NSMutableString *newString = [NSMutableString string];
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
        if (substring.Nitya_isDigit) {
            [newString appendString:substring];
        }
    }];

请注意,我们也删除了小数点。

现在让我们定义一些描述所需格式的常量:

    static const int requiredFractionalDigitCount = 2;
    static const int requiredIntegerDigitCount = 1;
    static const int requiredDigitCount = requiredFractionalDigitCount + requiredIntegerDigitCount;
    static const int maxDigitCount = 12;

第二步是如果数字太多,则修剪字符串前面的字符:

    if (newString.length > maxDigitCount) {
        [newString replaceCharactersInRange:NSMakeRange(0, newString.length - maxDigitCount) withString:@""];
    }

我们还希望修剪字符串中的前导零(或者从最初的“0.00”字符串中的零将保持不变并且看起来很奇怪):

    while (newString.length > 0 && [newString characterAtIndex:0] == '0') {
        [newString replaceCharactersInRange:NSMakeRange(0, 1) withString:@""];
    }

现在我们要确保我们有足够的数字,在必要时将零放回前面:

    while (newString.length < requiredDigitCount) {
        [newString insertString:@"0" atIndex:0];
    }

最后,我们将小数点放回:

    [newString insertString:@"." atIndex:newString.length - requiredFractionalDigitCount];
    return newString;
}

这是辅助方法Nitya_isDigit

- (BOOL)Nitya_isDigit {
    static dispatch_once_t once;
    static NSCharacterSet *digits;
    dispatch_once(&once, ^{
        digits = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
    });

    return self.length == 1 && [digits characterIsMember:[self characterAtIndex:0]];
}

@end

答案 1 :(得分:0)

您可以将文本字段文本右对齐,以便从右到左获取文本。

要根据需要格式化文本,您只需执行以下操作:

最初将文本字段文本设置为0.00

 #pragma text field delegate methods
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

 if ([textField.text isEqualToString:@"0.00"]) {
        textField.text=@"";
    }
    _enteredString=_textField.text;
    _textFieldString=[_enteredString stringByAppendingString:string];
    _yourLabel.text=[self formatNumber:_textFieldString];
    // you have to format this _yourLabel.text to fit into the textfield in your required format
    // Else if you dont want to do additional stuff, simply put the label on top of the textfield.
    return YES;
}

-(NSString *)formatNumber:(NSString *) enteredCharacter{

    float enteredValue=[enteredCharacter floatValue]*0.01;
   NSNumber *enteredNum=[NSNumber numberWithFloat:enteredValue];
    return [enteredNum stringValue];
}

注意:确保只输入文字字段中的数字。