Убедитесь, что вход в поле UITextField является только числовым



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

696   22  

22 ответов:

Я использую этот код в моем приложении 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]];
    }
}

Вы можете сделать это в несколько строк, как это:

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

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

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

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

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

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

Если вы хотите, чтобы пользователю было разрешено вводить только цифры, вы можете сделать свой 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: или аналогичный.

#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;
}

вот несколько однострочных строк, которые объединяют ответ Питера Льюиса выше (проверьте, что вход в 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]

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

- (BOOL) isIntegerNumber: (NSString*)input
{
    return [input integerValue] != 0 || [input isEqualToString:@"0"];
}

вы можете использовать двойное значение вашей строки, как

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

Я думаю, что это вернет a как 0.0, если строка недопустима (это может вызвать исключение, и в этом случае вы можете просто поймать его, документы говорят 0.0 tho). подробнее здесь

Привет была точно такая же проблема, и я не вижу ответа, который я использовал, так что вот он.

Я создал и подключил свое текстовое поле через IB. Когда я подключил его к своему коду через Control+Drag, я выбрал Action, а затем выбрал событие редактирования Changed. Это запускает метод для каждой символьной записи. Вы можете использовать другое событие, чтобы удовлетворить.

затем я использовал этот простой код для замены текста. Обратите внимание, что я создал свой собственный набор символов, чтобы включить десятичный / период символ и цифры. В основном разделяет строку на недопустимые символы, а затем присоединяется к ним с пустой строкой.

- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender {
        NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
        NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet;
        sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""];
}

кредиты: удалить все, кроме чисел из NSString

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

@interface NSString (Extension)

- (BOOL) isAnEmail;
- (BOOL) isNumeric;

@end

@implementation NSString (Extension)

/**
 *  Determines if the current string is a valid email address.
 *
 *  @return BOOL - True if the string is a valid email address.
 */

- (BOOL) isAnEmail
{
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];

    return [emailTest evaluateWithObject:self];
}

/**
 *  Determines if the current NSString is numeric or not. It also accounts for the localised (Germany for example use "," instead of ".") decimal point and includes these as a valid number.
 *
 *  @return BOOL - True if the string is numeric.
 */

- (BOOL) isNumeric
{
    NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
    NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
    [decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];

    NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
    NSRange r = [self rangeOfCharacterFromSet: nonNumbers];

    if (r.location == NSNotFound)
    {
        // check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
        int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
        return (numberOfOccurances > 1) ? NO : YES;
    }
    else return NO;
}

@end

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

в interface builder выберите 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];
  }
}
@property (strong) NSNumberFormatter *numberFormatter;
@property (strong) NSString *oldStringValue;

- (void)awakeFromNib 
{
  [super awakeFromNib];
  self.numberFormatter = [[NSNumberFormatter alloc] init];
  self.oldStringValue = self.stringValue;
  [self setDelegate:self];
}

- (void)controlTextDidChange:(NSNotification *)obj
{
  NSNumber *number = [self.numberFormatter numberFromString:self.stringValue];
  if (number) {
    self.oldStringValue = self.stringValue;
  } else {
    self.stringValue = self.oldStringValue;
  }
}

старая нить, но стоит упомянуть, что Apple представила NSRegularExpression в iOS 4.0. (Принимая регулярное выражение из ответа Питера)

// Look for 0-n digits from start to finish
NSRegularExpression *noFunnyStuff = [NSRegularExpression regularExpressionWithPattern:@"^(?:|0|[1-9]\d*)(?:\.\d*)?$" options:0 error:nil];

// There should be just one match
if ([noFunnyStuff numberOfMatchesInString:<#theString#> options:0 range:NSMakeRange(0, <#theString#>.length)] == 1)
{
    // Yay, digits!
}

Я предлагаю хранить NSRegularExpression где-то экземпляр.

- (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;
}

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

создать целочисленный форматер чисел (в UIApplicationDelegate, чтобы его можно было использовать повторно):

@property (nonatomic, retain) NSNumberFormatter *integerNumberFormatter;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Create and configure an NSNumberFormatter for integers
    integerNumberFormatter = [[NSNumberFormatter alloc] init];
    [integerNumberFormatter setMaximumFractionDigits:0];

    return YES;
}

использовать фильтр в UITextFieldDelegate:

@interface MyTableViewController : UITableViewController <UITextFieldDelegate> {
    ictAppDelegate *appDelegate;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Make sure the proposed string is a number
    NSNumberFormatter *inf = [appDelegate integerNumberFormatter];
    NSString* proposedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSNumber *proposedNumber = [inf numberFromString:proposedString];
    if (proposedNumber) {
        // Make sure the proposed number is an integer
        NSString *integerString = [inf stringFromNumber:proposedNumber];
        if ([integerString isEqualToString:proposedString]) {
            // proposed string is an integer
            return YES;
        }
    }

    // Warn the user we're rejecting the change
    AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
    return NO;
}

Не так элегантно, но простой :)

- (BOOL) isNumber: (NSString*)input
{
    return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"];
}

принимать десятичные значения в текстовых полях с одним (.)точка работает с iPad и iPhone в Swift 3

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted

        let components = string.components(separatedBy: inverseSet)

        let filtered = components.joined(separator: "")

        if filtered == string {
            return true
        } else {
            if string == "." {
                let countdots = textField.text!.components(separatedBy:".").count - 1
                if countdots == 0 {
                    return true
                }else{
                    if countdots > 0 && string == "." {
                        return false
                    } else {
                        return true
                    }
                }
            }else{
                return false
            }
        }
    }

чтобы быть более международным (и не только нам окрашенным ; -)) просто замените в коде выше на

-(NSNumber *) getNumber
{
  NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
  NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
  return [self getNumberWithLocale: [l_en autorelease] ];
}

этот ответ использует NSFormatter, как было сказано ранее. Проверьте это:

@interface NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale;  
- (BOOL) isNumber;
- (NSNumber *) getNumber; 
- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale;
@end

@implementation NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale
{
    return [self getNumberWithLocale:stringLocale] != nil;
}
- (BOOL) isNumber
{
    return [ self getNumber ] != nil;
}
- (NSNumber *) getNumber
{
    NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: @"en_US"] ;  
    return [self getNumberWithLocale: [l_en autorelease] ];
}

- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale
{
    NSNumberFormatter *formatter = [[ [ NSNumberFormatter alloc ] init ] autorelease];
    [formatter setLocale: stringLocale ];
    return [ formatter numberFromString:self ]; 
}
@end

Я надеюсь, что это поможет кому-то. =)

   #import "NSString+Extension.h"

//@interface NSString (Extension)
//
//- (BOOL) isAnEmail;
//- (BOOL) isNumeric;
//
//@end

@implementation NSString (Extension)
 - (BOOL) isNumeric
    {
        NSString *emailRegex = @"[0-9]+";
        NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];

        return [emailTest evaluateWithObject:self];

    //    NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
    //    NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
    //    [decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
    //    
    //    NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
    //    NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
    //    
    //    if (r.location == NSNotFound)
    //    {
    //        // check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
    //        int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
    //        return (numberOfOccurances > 1) ? NO : YES;
    //    }
    //    else return NO;
    }

В Swift 4:

let formatString = "12345"
if let number = Decimal(string:formatString){

    print("String contains only number")
}
else{
    print("String doesn't contains only number")
}

это охватывает: управление десятичной частью (включая количество разрешенных десятичных знаков), управление копированием/вставкой, международные разделители.

действия:

  1. убедитесь, что ваш контроллер представления наследует от UITextFieldDelegate

    класс MyViewController: UIViewController, UITextFieldDelegate {...

  2. В метод viewDidLoad, установить свой контроль делегат для себя:

    переопределить функцию viewDidLoad() { супер.viewDidLoad(); ваш текстфилд.делегат = собственн }

  3. реализуйте следующий метод и обновите константу "decsAllowed" с требуемым количеством десятичных знаков или 0, если вы хотите натуральное число.

Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let decsAllowed: Int = 2
    let candidateText = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
    let decSeparator: String = NumberFormatter().decimalSeparator!;

    let splitted = candidateText.components(separatedBy: decSeparator)
    let decSeparatorsFound = splitted.count - 1
    let decimalPart = decSeparatorsFound > 0 ? splitted.last! : ""
    let decimalPartCount = decimalPart.characters.count

    let characterSet = NSMutableCharacterSet.decimalDigit()
    if decsAllowed > 0 {characterSet.addCharacters(in: decSeparator)}

    let valid = characterSet.isSuperset(of: CharacterSet(charactersIn: candidateText)) &&
                decSeparatorsFound <= 1 &&
                decsAllowed >= decimalPartCount

    return valid
}

Если после этого вам нужно безопасно преобразовать эту строку в число, вы можете просто использовать Double (yourstring) или Int(yourstring) тип cast, или более академический способ:

let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!

Comments

    Ничего не найдено.