Jak sprawdzić poprawność danych wejściowych ciągu w pliku UITextField
? Chcę sprawdzić, czy ciąg jest liczbą, w tym kropkami dziesiętnymi.
objective-c
cocoa-touch
validation
nsstring
uitextfield
g. rewolucja
źródło
źródło
+ (BOOL) TextIsValidValue:(NSString*)newText:(double)&value:
...(?:|0|[1-9]\\d*)(?:\\.\\d*)
aby zobaczyć, co to oznacza. Zobacz także Regex WikipediaMożesz to zrobić w kilku linijkach w ten sposób:
BOOL valid; NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet]; NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text]; valid = [alphaNums isSupersetOfSet:inStringSet]; if (!valid) // Not numeric
- służy do sprawdzania poprawności danych wejściowych tylko znaków numerycznych. Zapoznaj się z dokumentacją dotyczącą
NSCharacterSet
innych opcji. Możesz użyć characterSetWithCharactersInString, aby określić dowolny zestaw prawidłowych znaków wejściowych.źródło
Możesz to zrobić na kilka sposobów:
nil
nie może.IMO, użycie czegoś takiego jak
-[NSString doubleValue]
nie byłoby najlepszą opcją, ponieważ oba@"0.0"
i@"abc"
będą miały doubleValue równe 0. Wszystkie metody * value zwracają 0, jeśli nie są w stanie poprawnie przekonwertować ciągu, więc byłoby trudno rozróżnić prawidłowy ciąg@"0"
i niepoprawny ciąg. Coś w rodzajustrtol
funkcji C miałoby ten sam problem.Myślę, że użycie NSNumberFormatter byłoby najlepszą opcją, ponieważ bierze pod uwagę lokalizację (tj. Liczbę
@"1,23"
w Europie, w porównaniu@"1.23"
z USA).źródło
NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; NSNumber * n = [f numberFromString:@"34jfkjdskj80"]; NSLog(@"N: %@", n);
NSScanner
przykładNSNumberFormatter
, bierze pod uwagę ustawienia regionalne, pod warunkiem, że używaszsetLocale:
na obiekcie skanera (możesz na przykład podać[NSLocale currentLocale]
).Jeśli chcesz, aby użytkownik mógł wprowadzać tylko cyfry, możesz sprawić, by ViewController implementował część UITextFieldDelegate i zdefiniował tę metodę:
- (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]; }
Prawdopodobnie są bardziej wydajne sposoby, ale uważam, że jest to całkiem wygodny sposób. Metoda powinna być łatwa do dostosowania do walidacji podwójnych lub czegokolwiek innego: po prostu użyj scanDouble: lub podobnego.
źródło
#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; }
źródło
Oto kilka jednowierszowych, które łączą powyższą odpowiedź Petera Lewisa ( Sprawdź, czy dane wejściowe do UITextField są tylko liczbowe ) z 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]
źródło
Dla testu liczb całkowitych będzie to:
- (BOOL) isIntegerNumber: (NSString*)input { return [input integerValue] != 0 || [input isEqualToString:@"0"]; }
źródło
Możesz użyć doubleValue swojego ciągu, na przykład
NSString *string=@"1.22"; double a=[string doubleValue];
Myślę, że zwróci to wartość 0,0, jeśli łańcuch jest nieprawidłowy (może to spowodować zgłoszenie wyjątku, w którym to przypadku można go po prostu złapać, dokumentacja mówi, że jest to 0,0). więcej informacji tutaj
źródło
Cześć, miałem dokładnie ten sam problem i nie widzę odpowiedzi, której użyłem, opublikowanej, więc oto jest.
Stworzyłem i połączyłem swoje pole tekstowe przez IB. Kiedy połączyłem go z moim kodem za pomocą Control + Drag, wybrałem Action, a następnie wybrałem zdarzenie Editing Changed. Spowoduje to wyzwolenie metody przy każdym wpisie znaku. Możesz użyć innego zdarzenia.
Następnie użyłem tego prostego kodu, aby zastąpić tekst. Zwróć uwagę, że stworzyłem własny zestaw znaków zawierający znaki dziesiętne / kropki i liczby. Zasadniczo oddziela ciąg od nieprawidłowych znaków, a następnie łączy je ponownie z pustym ciągiem.
- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender { NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"]; NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet; sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""]; }
Kredyty: usuń wszystkie oprócz liczb z NSString
źródło
Spóźniona gra, ale tutaj przydatna mała kategoria, której używam, która uwzględnia miejsca dziesiętne i używany do tego lokalny symbol. link do jego istoty tutaj
@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
źródło
- (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; }
źródło
IMO najlepszym sposobem na osiągnięcie celu jest wyświetlanie klawiatury numerycznej zamiast zwykłej klawiatury. Ogranicza to, które klucze są dostępne dla użytkownika. Zmniejsza to potrzebę przeprowadzania walidacji, a co ważniejsze, zapobiega popełnieniu błędu przez użytkownika. Klawiatura numeryczna jest również znacznie przyjemniejsza do wprowadzania cyfr, ponieważ klawisze są znacznie większe.
W konstruktorze interfejsu wybierz UITextField, przejdź do Inspektora atrybutów i zmień „Typ klawiatury” na „Pad dziesiętny”.
Dzięki temu klawiatura będzie wyglądać tak:
Pozostaje tylko upewnić się, że użytkownik nie wprowadza do dwóch miejsc po przecinku. Możesz to zrobić podczas edycji. Dodaj następujący kod do kontrolera widoku. Ten kod usuwa drugie miejsce po przecinku, gdy tylko zostanie wprowadzony. Wydaje się użytkownikowi, że 2. miejsce po przecinku nigdy nie pojawiło się na pierwszym miejscu.
- (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]; } }
źródło
@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; } }
źródło
Stary wątek, ale warto wspomnieć, że Apple wprowadziło
NSRegularExpression
iOS 4.0. (Biorąc wyrażenie regularne z odpowiedzi Piotra)// 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! }
Proponuję
NSRegularExpression
gdzieś przechowywać instancję.źródło
Chciałem mieć pole tekstowe, które dopuszcza tylko liczby całkowite. Oto, na czym skończyłem (używając informacji z tego miejsca i gdzie indziej):
Utwórz program formatujący liczby całkowite (w UIApplicationDelegate, aby można go było ponownie wykorzystać):
@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; }
Użyj filtra w 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; }
źródło
Nie tak elegancko, ale prosto :)
- (BOOL) isNumber: (NSString*)input { return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"]; }
źródło
Akceptuj wartości dziesiętne w polach tekstowych z pojedynczą (.) Kropką na iPadzie i iPhonie w 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 } } }
źródło
Aby być bardziej międzynarodowym (i nie tylko w kolorze amerykańskim ;-)) po prostu zastąp w powyższym kodzie przez
-(NSNumber *) getNumber { NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier]; NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ; return [self getNumberWithLocale: [l_en autorelease] ]; }
źródło
Ta odpowiedź używa NSFormatter, jak wspomniano wcześniej. Sprawdź to:
@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
Mam nadzieję, że to komuś pomoże. =)
źródło
#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; }
źródło
W Swift 4:
let formatString = "12345" if let number = Decimal(string:formatString){ print("String contains only number") } else{ print("String doesn't contains only number") }
źródło
Obejmuje to: kontrolę części dziesiętnej (w tym dozwoloną liczbę miejsc po przecinku), kontrolę kopiowania / wklejania, separatory międzynarodowe.
Kroki:
Upewnij się, że kontroler widoku dziedziczy po UITextFieldDelegate
klasa MyViewController: UIViewController, UITextFieldDelegate {...
W viewDidLoad ustaw delegata kontroli na siebie:
nadpisz func viewDidLoad () {super.viewDidLoad (); yourTextField.delegate = self}
Zaimplementuj następującą metodę i zaktualizuj stałą „decsAllowed” o żądaną liczbę miejsc po przecinku lub 0, jeśli chcesz uzyskać liczbę naturalną.
Szybki 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 }
Jeśli później chcesz bezpiecznie przekonwertować ten ciąg na liczbę, możesz po prostu użyć rzutowania typu Double (yourstring) lub Int (yourstring) lub w bardziej akademicki sposób:
let formatter = NumberFormatter() let theNumber: NSNumber = formatter.number(from: yourTextField.text)!
źródło