Как проверить ввод символов в UITextField, когда пользователь вводит символы и предотвращает недопустимые символы - PullRequest
12 голосов
/ 18 февраля 2012

Во-первых, я настроил клавиатуру для UITextField, чтобы использовать число с десятичным стилем. Таким образом, пользователь может вводить только цифры и один десятичный знак.

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

Ответы [ 6 ]

45 голосов
/ 20 февраля 2012

Решение в итоге оказалось довольно тривиальным.К сожалению, многие вопросы и ответы, связанные с этим вопросом, касаются проверки или форматирования числовых значений, а не управления тем, что может ввести пользователь.

Следующая реализация метода делегата 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.11.11, .1, .11.Обратите внимание, что эта реализация не заменяет строку текстового поля, что может привести к рекурсии.Это решение просто отклоняет следующий символ, введенный пользователем, если 'newString' не соответствует регулярному выражению.

5 голосов
/ 07 апреля 2013

Хорошо!Если кому-то нужно, чтобы он работал с неамериканскими валютами: евро или другие с дробью, разделенной запятой вместо точки, используйте эту:

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

Единственное отличие состоит в том, что допускается запятая или точка.([\, \.] - или. или,) Единственная хитрость в том, что вам нужно заменить запятую на точку при использовании полученного вами числа, потому что компьютер использует точку для разделения дроби, а не запятой.

3 голосов
/ 18 февраля 2012

Стандартный способ решения этой проблемы в iOS - это добавление UITextFieldDelegate к вашему UITextField и внедрение метода textField:shouldChangeCharactersInRange:replacementString:. Внутри этого метода вы можете проверить, что строка имеет правильную «форму» для ваших целей (одна точка, не более двух цифр после точки и т. Д.) И указать другую строку, если ввод не соответствует ожидаемому формату.

1 голос
/ 20 ноября 2014

После долгих экспериментов и изучения других решений (которые кажутся слишком сложными и сложными), я пришел к следующему, что не позволяет пользователю вводить что-либо, кроме действительной суммы в валюте. По сути, пусть экземпляр NSNumberFormatter (созданный в другом месте в viewController) выполняет тяжелую работу:

  • 1) преобразовать текст в число (если ноль, то есть недопустимые символы, поэтому верните НЕТ)
  • 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;

}

0 голосов
/ 27 сентября 2017

Для 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
}
0 голосов
/ 21 февраля 2012

Вы можете передать строку uitexfield в метод ниже, он вернет да / нет .. соответственно вы можете показать ошибку

- (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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...