Ограничение ввода текстового поля только одной десятичной точкой

Я создал текстовое поле для ввода суммы денег. Я хочу, чтобы пользователь мог вводить только одну десятичную точку. Я реализовал это в методе -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string.

В общем случае он работает нормально, но если нажать клавишу Backspace и удалить одиночную запятую, то после этого он все равно считает, что десятичная запятая была введена, и поэтому не принимает десятичную точку снова.

Мне нужно сбросить флаг decimalPointEntered всякий раз, когда десятичная точка удаляется нажатием клавиши Backspace. Как это сделать ?


person utsabiem    schedule 10.11.2011    source источник
comment
Я решил эту проблему в этом ответе. Пожалуйста, проверь это. stackoverflow.com/questions/27883171/   -  person sn86    schedule 20.06.2017


Ответы (10)


Это отлично работает для меня. Попробуйте этот код:

-(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;
}
person user9930    schedule 18.11.2011
comment
Я думаю, что большая часть Европы использует запятую, но в Великобритании мы используем точку. В Германии у вас есть 1 000,00 долларов США, а в Великобритании и США у нас есть 1 000 долларов США. Эти различия раздражают при кодировании, но не так сложно, как печатать на немецкой клавиатуре, где клавиши Y и Z поменяны местами! - person Josh; 16.11.2014

Вот что я использую:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (!numberFormatter) {
        numberFormatter = [[NSNumberFormatter alloc]init];
        //[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

    }
    NSNumber *test = [numberFormatter numberFromString:[self.text stringByAppendingString: string]];  // in case we entered two decimals

    return (test != nil);

}
person Paul Heller    schedule 11.12.2012

Я ограничиваю своего пользователя вводом суммы, которая должна быть такой

  • Пользователь должен иметь возможность вводить только 0-9 и десятичные числа. символы
  • Только один десятичный знак. разрешенный персонаж
  • Максимум 5 цифр перед запятой.
  • Максимум 2 цифры после запятой.

40543,48

Поэтому я обновил метод shouldChangeCharactersInRange таким образом.

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

    if (textField == self.txtFieldTransferAmount)
    {
        NSString *updatedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
        NSArray *stringsArray = [updatedText componentsSeparatedByString:@"."];

        // Before decimal only 5 digit allowed
        if (stringsArray.count > 0)
        {
            NSString *dollarAmount = stringsArray[0];
            if (dollarAmount.length > 5)
                return NO;
        }

        // After decimal only 2 digit allowed
        if (stringsArray.count > 1)
        {
            NSString *centAmount = stringsArray[1];
            if (centAmount.length > 2)
                return NO;
        }

        // Only one . decimal allowed
        if (stringsArray.count > 2)
            return NO;

        if (textField.text.length < 8) {
            //User should able to enter only 0-9 and . characters
            NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];
            NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
            return [string isEqualToString:filtered];
        }
        else
        {
            if (range.length > 0)
            {
                return true;
            }
            else{
                return false;
            }
        }
    }
    return true;
}
person swiftBoy    schedule 14.03.2016

У меня очень похожее решение. Работал лучше для меня. Он также проверяет ввод текста.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSLog(@"in shouldChangeCharactersInRange");


    if([string length]==0){
        return YES;
    }

    //Validate Character Entry
    NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789,."];
    for (int i = 0; i < [string length]; i++) {
        unichar c = [string characterAtIndex:i];

        if ([myCharSet characterIsMember:c]) {

            //now check if string already has 1 decimal mark
            NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
            NSArray *sep = [newString componentsSeparatedByString:@"."];
            NSLog(@"sep: %@ count: %d" ,sep,[sep count]);
            if([sep count]>2) return NO;
            return YES;

        }

    }

    return NO;
}
person oberbaum    schedule 04.04.2012

Может кому поможет..

NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        // if . at the beggining
        if ([newString isEqualToString:@"."] && newString.length== 1) {
            textField.text = @"0.";
            return NO;
        }

        // do not allow . more then once
        NSArray *components = [newString componentsSeparatedByString:@"."];
        if([components count] > 2)
        {
            return NO;
        }
person Surender Rathore    schedule 24.07.2013

Похоже, вам нужен NSNumberFormatter. .

person NSResponder    schedule 10.11.2011

Попробуйте это, это быстрый код, но вы можете обратиться к логике: -

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 
}
person Abhijeet Mallick    schedule 17.08.2016

Это самый простой способ сделать это.


-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSArray *explodedNumbersArray = [newString componentsSeparatedByString:@"."];

    // We check if the array has 3 or more items which means that it has 2 decimal places or more
    // we return NO if that happens so that the textfield will not recognize input
    if([explodedNumbersArray count] >= 3) {
        return NO;
    }

    return YES;
}

Примечание. Убедитесь, что представление или контроллер представления, которые должны получать уведомления делегата, должны соответствовать UITextFieldDelegate.

person Zaldy    schedule 03.12.2013

Я использую этот метод, чтобы ограничить количество десятичных символов до одного И разрешить пользователю вводить отрицательные суммы, если это необходимо (например, для скидок):

NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"1234567890.-"] invertedSet];
if ([string rangeOfCharacterFromSet:cs].location == NSNotFound) {

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

    // check number of decimal chars used (maximum of one)
    NSArray *array = [newString componentsSeparatedByString:@"."];
    if ([array count] <= 2) {

        // check negative chars (maximum of one AND it must be at the front)
        array = [newString componentsSeparatedByString:@"-"];

        if (1 == [array count]) {
            return YES; // no negatives
        } else if (2 == [array count]) {
            return ('-' == [newString characterAtIndex:0]); // return YES if first char is negative only
        } else {
            return NO; // too many negative chars
        }
    } else {
        return NO; // too many decimal chars
    }
} else {
    return NO; // invalid character
}
person pheedsta    schedule 02.04.2014

Я всегда предпочел бы регулярное выражение некоторому правилу, основанному на коде, для таких сценариев.

Чтобы ограничить одну десятичную точку и один символ после нее, используйте ниже;

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
   // Only allow one decimal point and 1 digit after it
   NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
   NSString *expression = @"^[0-9]$*((\\.|,)[0-9]{0,1})?$";
   NSError *error = nil;
   NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
   NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
   return numberOfMatches != 0;
   return YES;
 }

Приведенный выше код гарантирует, что текстовое поле содержит только одну десятичную точку и только один символ после нее.

Вы можете поиграть с этим регулярным выражением и создать правило в соответствии с вашими требованиями.

person Shobhit C    schedule 25.07.2018