Как проверить строковый ввод на UITextField
? Я хочу проверить, что строка является числовой, включая десятичные точки.
Убедитесь, что вход в UITextField только числовой
Ответ 1
Я использую этот код в своем приложении 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]];
}
}
Ответ 2
Вы можете сделать это в нескольких строках:
BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];
if (!valid) // Not numeric
- это для проверки ввода только числовых символов. Посмотрите документацию для NSCharacterSet
для других параметров. Вы можете использовать characterSetWithCharactersInString, чтобы указать любой набор допустимых входных символов.
Ответ 3
Есть несколько способов сделать это:
- Использовать NSNumberFormatter numberFromString: метод. Это вернет NSNumber, если он сможет корректно проанализировать строку или
nil
, если это невозможно. - Использовать NSScanner
- Сбросьте любой нечисловой символ и посмотрите, соответствует ли строка
- Используйте регулярное выражение
IMO, использование чего-то типа -[NSString doubleValue]
не было бы лучшим вариантом, потому что как @"0.0"
, так и @"abc"
будет иметь doubleValue из 0. Методы значения * все возвращают 0, если они не могут преобразовать Строка правильно, поэтому было бы трудно провести различие между законной строкой @"0"
и недействительной строкой. Что-то вроде функции C strtol
будет иметь такую же проблему.
Я думаю, что использование NSNumberFormatter было бы лучшим вариантом, поскольку он учитывает локаль (т.е. число @"1,23"
в Европе по сравнению с @"1.23"
в США).
Ответ 4
Если вы хотите, чтобы пользователю разрешалось вводить цифры, вы можете заставить свой 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: или аналогичный.
Ответ 5
#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;
}
Ответ 6
Вот несколько однострочных строк, которые сочетают ответ Питера Льюиса выше (Убедитесь, что вход в 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]
Ответ 7
Для целочисленного теста это будет:
- (BOOL) isIntegerNumber: (NSString*)input
{
return [input integerValue] != 0 || [input isEqualToString:@"0"];
}
Ответ 8
Вы можете использовать doubleValue своей строки, например
NSString *[email protected]"1.22";
double a=[string doubleValue];
Я думаю, что это вернет как 0.0, если строка недействительна (это может вызвать исключение, и в этом случае вы можете просто ее поймать, docs говорят 0.0 tho). подробнее здесь
Ответ 9
Привет имел ту же самую проблему, и я не вижу ответа, который я использовал, так что вот оно.
Я создал и подключил свое текстовое поле через 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:@""];
}
Ответ 10
Поздно к игре, но здесь удобная небольшая категория, которую я использую для учета десятичных знаков и используемого для нее локального символа. ссылка на его gist здесь
@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
Ответ 11
IMO - лучший способ достичь вашей цели - отобразить цифровую клавиатуру, а не обычную клавиатуру. Это ограничивает, какие ключи доступны пользователю. Это облегчает необходимость проверки, и, что более важно, это мешает пользователю совершить ошибку. Цифровая клавиатура также намного удобнее вводить цифры, потому что клавиши значительно больше.
В построителе интерфейса выберите 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 more than one decimal
textField.text = [text substringToIndex:text.length - 1];
}
}
Ответ 12
@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;
}
}
Ответ 13
- (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;
}
Ответ 14
Мне нужно текстовое поле, которое допускало только целые числа. Вот что я получил (используя информацию здесь и в другом месте):
Создать целочисленное число форматера (в 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;
}
Ответ 15
Не так элегантно, но просто:)
- (BOOL) isNumber: (NSString*)input
{
return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"];
}
Ответ 16
Старый поток, но стоит упомянуть, что 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
где-то.
Ответ 17
Принять десятичные значения в текстовых полях с одной (.) точкой, работающей с 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
}
}
}
Ответ 18
В этом ответе используется 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
Я надеюсь, что это поможет кому-то. =)
Ответ 19
Чтобы быть более международным (и не только американским цветом;-)), просто замените в коде выше
-(NSNumber *) getNumber
{
NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
Ответ 20
#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;
}
Ответ 21
В Swift 4:
let formatString = "12345"
if let number = Decimal(string:formatString){
print("String contains only number")
}
else{
print("String doesn't contains only number")
}
Ответ 22
Это включает: Управление десятичной частью (включая количество разрешенных десятичных знаков), контроль копирования/вставки, международные разделители.
Шаги:
-
Убедитесь, что ваш контроллер представления наследуется от UITextFieldDelegate
класс MyViewController: UIViewController, UITextFieldDelegate {...
-
В viewDidLoad установите свой делегат управления самостоятельно:
переопределить func viewDidLoad() { super.viewDidLoad(); yourTextField.delegate = self }
-
Внедрите следующий метод и обновите константу 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)!