Убедитесь, что вход в UITextField только числовой

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

Я использую этот код в своем приложении 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, чтобы указать любой набор допустимых входных символов.

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

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

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

Я думаю, что использование 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"]; } 

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

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

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

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

Я создал и подключил свое текстовое поле через IB. Когда я подключил его к моему коду через Control + Drag, я выбрал Action, а затем выбрал событие Editing 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._%+-][email protected][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 

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

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

введите описание изображения здесь

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

введите описание изображения здесь

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

 - (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  { 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. Убедитесь, что ваш controller представления наследуется от UITextFieldDelegate

    class MyViewController: UIViewController, UITextFieldDelegate {…

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

    override func viewDidLoad () {super.viewDidLoad (); yourTextField.delegate = self}

  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 } 

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

 let formatter = NumberFormatter() let theNumber: NSNumber = formatter.number(from: yourTextField.text)! 
  • Как установить атрибут maxlength на h: inputTextarea
  • Бесконечная петля с cin при наборе строки, в то время как число ожидается
  • JSF не поддерживает проверку кросс-поля, есть ли обходной путь?
  • Как добавить правило не равно правилу в jQuery.validation
  • Получение приглашения для входа с помощью встроенной проверки подлинности Windows
  • Какой алгоритм дает предложения в проверке орфографии?
  • Page_ClientValidate () с несколькими ValidationGroups - как показать несколько сводок одновременно?
  • Как заставить MVC проверять объект IValidatableObject
  • Как выполнить проверку в JSF, как создать пользовательский валидатор в JSF
  • Разрешить пользователю вводить HTML в ASP.NET MVC - ValidateInput или AllowHtml
  • Что означает == $ 0 (double equals dollar zero) в инструментах разработчика Chrome?
  • Давайте будем гением компьютера.