Убедитесь, что вход в UITextField является только числовым - PullRequest
82 голосов
/ 24 августа 2009

Как проверить правильность ввода строки в UITextField? Я хочу проверить, что строка числовая, включая десятичные точки.

Ответы [ 22 ]

115 голосов
/ 01 октября 2010

Вы можете сделать это в несколько строк следующим образом:

BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];    
if (!valid) // Not numeric

- это для проверки ввода только числовых символов. Посмотрите документацию для NSCharacterSet для других опций. Вы можете использовать characterSetWithCharactersInString, чтобы указать любой набор допустимых входных символов.

72 голосов
/ 24 августа 2009

Есть несколько способов сделать это:

  1. Использовать метод NSFumberFormatter numberFromString: метод. Это вернет NSNumber, если он может правильно проанализировать строку, или nil, если не сможет.
  2. Использовать NSScanner
  3. Удалите любой нечисловой символ и посмотрите, соответствует ли строка
  4. Используйте регулярное выражение

IMO, использование что-то вроде -[NSString doubleValue] было бы не лучшим вариантом, потому что оба значения @"0.0" и @"abc" будут иметь значение doubleValue, равное 0. Все методы * value возвращают 0, если они не могут преобразовать правильная строка, поэтому было бы трудно различить допустимую строку @"0" и недопустимую строку. Что-то вроде функции C strtol будет иметь такую ​​же проблему.

Я думаю, что использование NSNumberFormatter было бы наилучшим вариантом, поскольку оно учитывает локаль (т. Е. Число @"1,23" в Европе против @"1.23" в США).

34 голосов
/ 24 августа 2009

Я использую этот код в своем приложении Mac, такой же или похожий должен работать с iPhone. Он основан на регулярных выражениях RegexKitLite и окрашивает текст в красный цвет, когда он недействителен.

static bool TextIsValidValue( NSString* newText, double &value )
{
    bool result = false;

    if ( [newText isMatchedByRegex:@"^(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"] ) {
        result = true;
        value = [newText doubleValue];
    }
    return result;
}

- (IBAction) doTextChanged:(id)sender;
{
    double value;
    if ( TextIsValidValue( [i_pause stringValue], value ) ) {
        [i_pause setTextColor:[NSColor blackColor]];
        // do something with the value
    } else {
        [i_pause setTextColor:[NSColor redColor]];
    }
}
19 голосов
/ 17 ноября 2009

Если вы хотите, чтобы пользователю разрешалось вводить только цифры, вы можете заставить свой ViewController реализовать часть UITextFieldDelegate и определить этот метод:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];

  // The user deleting all input is perfectly acceptable.
  if ([resultingString length] == 0) {
    return true;
  }

  NSInteger holder;

  NSScanner *scan = [NSScanner scannerWithString: resultingString];

  return [scan scanInteger: &holder] && [scan isAtEnd];
}

Возможно, есть более эффективные способы, но я нахожу это довольно удобным способом. И метод должен быть легко адаптируем для проверки двойников или чего-либо еще: просто используйте scanDouble: или аналогичный.

13 голосов
/ 07 июля 2011
#pragma mark - UItextfield Delegate

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if ([string isEqualToString:@"("]||[string isEqualToString:@")"]) {
        return TRUE;
    }

    NSLog(@"Range ==%d  ,%d",range.length,range.location);
    //NSRange *CURRANGE = [NSString  rangeOfString:string];

    if (range.location == 0 && range.length == 0) {
        if ([string isEqualToString:@"+"]) {
            return TRUE;
        }
    }
    return [self isNumeric:string];
}

-(BOOL)isNumeric:(NSString*)inputString{
    BOOL isValid = NO;
    NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet];
    NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:inputString];
    isValid = [alphaNumbersSet isSupersetOfSet:stringSet];
    return isValid;
}
11 голосов
/ 18 марта 2013

Вот несколько однострочников, которые объединяют ответ Питера Льюиса выше ( Проверьте, что вход в UITextField только числовой ) с NSPredicates

    #define REGEX_FOR_NUMBERS   @"^([+-]?)(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"
    #define REGEX_FOR_INTEGERS  @"^([+-]?)(?:|0|[1-9]\\d*)?$"
    #define IS_A_NUMBER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_NUMBERS] evaluateWithObject:string]
    #define IS_AN_INTEGER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_INTEGERS] evaluateWithObject:string]
4 голосов
/ 26 декабря 2012

Для целочисленного теста это будет:

- (BOOL) isIntegerNumber: (NSString*)input
{
    return [input integerValue] != 0 || [input isEqualToString:@"0"];
}
3 голосов
/ 24 августа 2009

Вы можете использовать doubleValue вашей строки как

NSString *string=@"1.22";
double a=[string doubleValue];

Я думаю, что это вернет значение 0.0, если строка недопустима (это может вызвать исключение, и в этом случае вы можете просто перехватить ее, в документах указано 0.0 tho). больше информации здесь

3 голосов
/ 29 июля 2015
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if(string.length > 0)
    {
        NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
        NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];

        BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
        return stringIsValid;
    }
    return YES;
}
3 голосов
/ 09 октября 2015

IMO лучший способ для достижения вашей цели - это отображение цифровой клавиатуры, а не обычной клавиатуры. Это ограничивает какие ключи доступны пользователю. Это устраняет необходимость выполнять проверку и, что более важно, предотвращает ошибку пользователя. Цифровая клавиатура также намного удобнее для ввода цифр, потому что клавиши значительно больше.

В конструкторе интерфейса выберите UITextField, перейдите в инспектор атрибутов и измените «Тип клавиатуры» на «Десятичная клавиатура».

enter image description here

Это заставит клавиатуру выглядеть так:

enter image description here

Осталось только убедиться, что пользователь не вводит в двух десятичных разрядах. Вы можете сделать это, пока они редактируют. Добавьте следующий код в ваш контроллер представления. Этот код удаляет второе десятичное место после его ввода. Для пользователя это выглядит так, как будто 2-й знак после запятой никогда не появлялся.

- (void)viewDidLoad
{
  [super viewDidLoad];

  [self.textField addTarget:self
                    action:@selector(textFieldDidChange:)
           forControlEvents:UIControlEventEditingChanged];
}

- (void)textFieldDidChange:(UITextField *)textField
{
  NSString *text = textField.text;
  NSRange range = [text rangeOfString:@"."];

  if (range.location != NSNotFound &&
      [text hasSuffix:@"."] &&
      range.location != (text.length - 1))
  {
    // There's more than one decimal
    textField.text = [text substringToIndex:text.length - 1];
  }
}
...