Как мне проверить ввод строки в a UITextField
? Я хочу проверить, является ли строка числовой, включая десятичные точки.
Как мне проверить ввод строки в a 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]];
}
}
(?:|0|[1-9]\\d*)(?:\\.\\d*)
чтобы увидеть, что это означает. Также см. Regex Wikipedia
Вы можете сделать это в нескольких строках, например:
BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];
if (!valid) // Not numeric
- это для проверки ввода только числовых символов. Прочтите документацию, чтобы NSCharacterSet
узнать о других вариантах. Вы можете использовать characterSetWithCharactersInString, чтобы указать любой набор допустимых входных символов.
Есть несколько способов сделать это:
nil
не может.IMO, используя что - то вроде -[NSString doubleValue]
бы не самый лучший вариант , потому что как @"0.0"
и @"abc"
будет иметь doubleValue от 0. * Методы значение , все возвращаются 0 , если они не в состоянии преобразовать строку правильно, поэтому было бы трудно отличить допустимая строка @"0"
и недопустимая строка. Что-то вроде strtol
функции C будет иметь ту же проблему.
Я думаю, что использование NSNumberFormatter было бы лучшим вариантом, поскольку он принимает во внимание локаль (т. Е. Число @"1,23"
в Европе, а не @"1.23"
в США).
NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; NSNumber * n = [f numberFromString:@"34jfkjdskj80"]; NSLog(@"N: %@", n);
NSScanner
вроде бы NSNumberFormatter
учитывает языковой стандарт при синтаксическом анализе строки, при условии, что вы используете setLocale:
объект сканера (вы могли бы, например, предоставить [NSLocale currentLocale]
).
Если вы хотите, чтобы пользователю было разрешено вводить только цифры, вы можете заставить 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 *string=@"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._%+-]+@[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
- (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;
}
ИМО лучший способ достичь вашей цели - отобразить цифровую клавиатуру, а не обычную клавиатуру. Это ограничивает, какие ключи доступны пользователю. Это устраняет необходимость в проверке и, что еще более важно, предотвращает ошибку пользователя. Цифровая клавиатура также намного удобнее для ввода цифр, потому что клавиши значительно больше.
В построителе интерфейса выберите UITextField, перейдите в Инспектор атрибутов и измените «Тип клавиатуры» на «Десятичный блокнот».
В результате клавиатура будет выглядеть так:
Осталось только убедиться, что пользователь не вводит два десятичных знака. Вы можете сделать это, пока они редактируют. Добавьте следующий код в свой контроллер представления. Этот код удаляет второй десятичный разряд сразу после его ввода. Пользователю кажется, что второй знак после запятой никогда не появлялся.
- (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
где-нибудь хранить экземпляр.
Мне нужно текстовое поле, в котором разрешены только целые числа. Вот что у меня получилось (используя информацию отсюда и из других источников):
Создайте средство форматирования целых чисел (в 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")
}
Это включает: управление десятичной частью (включая количество разрешенных десятичных знаков), управление копированием / вставкой, международные разделители.
Шаги:
Убедитесь, что ваш контроллер представления наследуется от UITextFieldDelegate
класс MyViewController: UIViewController, UITextFieldDelegate {...
В viewDidLoad установите для своего управляющего делегата self:
переопределить функцию viewDidLoad () {super.viewDidLoad (); yourTextField.delegate = self}
Реализуйте следующий метод и обновите константу decsAllowed с желаемым количеством десятичных знаков или 0, если вы хотите натуральное число.
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) или более академическим способом:
let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!
+ (BOOL) TextIsValidValue:(NSString*)newText:(double)&value:
...