Vérifier qu’une entrée de UITextField est uniquement numérique

Comment valider l’entrée de chaîne dans un UITextField ? Je veux vérifier que la chaîne est numérique, y compris les points décimaux.

J’utilise ce code dans mon application Mac, le même ou similaire devrait fonctionner avec l’iPhone. Il est basé sur les expressions régulières RegexKitLite et transforme le texte en rouge lorsqu’il est invalide.

 static bool TextIsValidValue( NSSsortingng* 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 ssortingngValue], value ) ) { [i_pause setTextColor:[NSColor blackColor]]; // do something with the value } else { [i_pause setTextColor:[NSColor redColor]]; } } 

Vous pouvez le faire en quelques lignes comme ceci:

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

– Ceci permet de valider les entrées uniquement avec des caractères numériques. Regardez la documentation de NSCharacterSet pour les autres options. Vous pouvez utiliser characterSetWithCharactersInSsortingng pour spécifier tout ensemble de caractères d’entrée valides.

Il y a plusieurs façons de procéder:

  1. Utilisez la méthode numberFromSsortingng: de NSNumberFormatter. Cela retournera un NSNumber s’il peut parsingr correctement la chaîne, ou nil s’il ne le peut pas.
  2. Utilisez NSScanner
  3. Supprimer tout caractère non numérique et voir si la chaîne correspond toujours
  4. Utiliser une expression régulière

OMI, utiliser quelque chose comme -[NSSsortingng doubleValue] ne serait pas la meilleure option car @"0.0" et @"abc" auront une doubleValue de 0. Les méthodes * value retournent toutes 0 si elles ne peuvent pas convertir la chaîne correctement, il serait donc difficile de faire la distinction entre une chaîne légitime de @"0" et une chaîne non valide. Quelque chose comme la fonction strtol de C aurait le même problème.

Je pense que l’utilisation de NSNumberFormatter serait la meilleure option, car elle prend en compte les parameters régionaux (c.-à-d. Le nombre @"1,23" en Europe, contre @"1.23" aux États-Unis).

Si vous souhaitez qu’un utilisateur soit autorisé à entrer uniquement des chiffres, vous pouvez faire en sorte que votre ViewController implémente une partie de UITextFieldDelegate et définisse cette méthode:

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSsortingng:(NSSsortingng *)ssortingng { NSSsortingng *resultingSsortingng = [textField.text ssortingngByReplacingCharactersInRange: range withSsortingng: ssortingng]; // The user deleting all input is perfectly acceptable. if ([resultingSsortingng length] == 0) { return true; } NSInteger holder; NSScanner *scan = [NSScanner scannerWithSsortingng: resultingSsortingng]; return [scan scanInteger: &holder] && [scan isAtEnd]; } 

Il existe probablement des moyens plus efficaces, mais je trouve cela très pratique . Et la méthode devrait être facilement adaptable à la validation de doubles ou autre: utilisez simplement scanDouble: ou similaire.

 #pragma mark - UItextfield Delegate - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSsortingng:(NSSsortingng *)ssortingng { if ([ssortingng isEqualToSsortingng:@"("]||[ssortingng isEqualToSsortingng:@")"]) { return TRUE; } NSLog(@"Range ==%d ,%d",range.length,range.location); //NSRange *CURRANGE = [NSSsortingng rangeOfSsortingng:ssortingng]; if (range.location == 0 && range.length == 0) { if ([ssortingng isEqualToSsortingng:@"+"]) { return TRUE; } } return [self isNumeric:ssortingng]; } -(BOOL)isNumeric:(NSSsortingng*)inputSsortingng{ BOOL isValid = NO; NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet]; NSCharacterSet *ssortingngSet = [NSCharacterSet characterSetWithCharactersInSsortingng:inputSsortingng]; isValid = [alphaNumbersSet isSupersetOfSet:ssortingngSet]; return isValid; } 

Voici quelques lignes simples qui combinent la réponse de Peter Lewis ci-dessus ( Vérifiez qu’une entrée de UITextField est uniquement numérique ) avec NSPredicates

  #define REGEX_FOR_NUMBERS @"^([+-]?)(?:|0|[1-9]\\d*)(?:\\.\\d*)?$" #define REGEX_FOR_INTEGERS @"^([+-]?)(?:|0|[1-9]\\d*)?$" #define IS_A_NUMBER(ssortingng) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_NUMBERS] evaluateWithObject:ssortingng] #define IS_AN_INTEGER(ssortingng) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_INTEGERS] evaluateWithObject:ssortingng] 

Pour le test de nombre entier ce sera:

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

Vous pouvez utiliser la doubleValue de votre chaîne comme

 NSSsortingng *ssortingng=@"1.22"; double a=[ssortingng doubleValue]; 

Je pense que cela renverra un 0.0 si la chaîne n’est pas valide (cela peut déclencher une exception, auquel cas vous pouvez simplement l’attraper, les docs disent 0.0). plus d’infos ici

Salut avait exactement le même problème et je ne vois pas la réponse que j’ai utilisée posté, alors le voici.

J’ai créé et connecté mon champ de texte via IB. Lorsque je l’ai connecté à mon code via Control + Drag, j’ai choisi Action, puis sélectionné l’événement Editing Changed. Cela déclenche la méthode sur chaque entrée de caractère. Vous pouvez utiliser un événement différent pour convenir.

Ensuite, j’ai utilisé ce code simple pour remplacer le texte. Notez que j’ai créé mon propre jeu de caractères pour inclure le caractère décimal / période et les nombres. Fondamentalement sépare la chaîne sur les caractères non valides, puis les rejoint avec une chaîne vide.

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

Crédits: Supprimer tous les numéros sauf NSSsortingng

Plus tard dans le jeu, mais voici une petite catégorie pratique que j’utilise et qui tient compte des décimales et du symbole local utilisé. lien vers son esprit ici

 @interface NSSsortingng (Extension) - (BOOL) isAnEmail; - (BOOL) isNumeric; @end @implementation NSSsortingng (Extension) /** * Determines if the current ssortingng is a valid email address. * * @return BOOL - True if the ssortingng is a valid email address. */ - (BOOL) isAnEmail { NSSsortingng *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 NSSsortingng 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 ssortingng is numeric. */ - (BOOL) isNumeric { NSSsortingng *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]; NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInSsortingng: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 ssortingng. It should only appear once for the number to be numeric. int numberOfOccurances = [[self componentsSeparatedBySsortingng:localDecimalSymbol] count]-1; return (numberOfOccurances > 1) ? NO : YES; } else return NO; } @end 

La meilleure façon d’atteindre votre objective est d’afficher un clavier numérique plutôt que le clavier normal. Cela limite les clés disponibles pour l’utilisateur. Cela évite d’avoir à faire de la validation et, plus important encore, empêche l’utilisateur de commettre une erreur. Le pavé numérique est également beaucoup plus pratique pour entrer des chiffres car les touches sont sensiblement plus grandes.

Dans le générateur d’interface, sélectionnez le champ UITextField, accédez à l’inspecteur d’atsortingbuts et remplacez le “Type de clavier” par “Bloc décimal”.

entrer la description de l'image ici

Cela fera ressembler le clavier à ceci:

entrer la description de l'image ici

La seule chose qu’il rest à faire est de s’assurer que l’utilisateur n’entre pas deux décimales. Vous pouvez le faire pendant qu’ils sont en train de modifier. Ajoutez le code suivant à votre contrôleur de vue. Ce code supprime une seconde décimale dès son entrée. Il apparaît à l’utilisateur comme si la 2ème décimale ne figurait jamais en premier lieu.

 - (void)viewDidLoad { [super viewDidLoad]; [self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; } - (void)textFieldDidChange:(UITextField *)textField { NSSsortingng *text = textField.text; NSRange range = [text rangeOfSsortingng:@"."]; if (range.location != NSNotFound && [text hasSuffix:@"."] && range.location != (text.length - 1)) { // There's more than one decimal textField.text = [text subssortingngToIndex:text.length - 1]; } } 
 @property (strong) NSNumberFormatter *numberFormatter; @property (strong) NSSsortingng *oldSsortingngValue; - (void)awakeFromNib { [super awakeFromNib]; self.numberFormatter = [[NSNumberFormatter alloc] init]; self.oldSsortingngValue = self.ssortingngValue; [self setDelegate:self]; } - (void)controlTextDidChange:(NSNotification *)obj { NSNumber *number = [self.numberFormatter numberFromSsortingng:self.ssortingngValue]; if (number) { self.oldSsortingngValue = self.ssortingngValue; } else { self.ssortingngValue = self.oldSsortingngValue; } } 

Vieux thread, mais il convient de mentionner que Apple a introduit NSRegularExpression dans iOS 4.0. (Prenant l’expression régulière de la réponse de Peter)

 // 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 numberOfMatchesInSsortingng:< #theString#> options:0 range:NSMakeRange(0, < #theString#>.length)] == 1) { // Yay, digits! } 

Je suggère de stocker l’instance NSRegularExpression quelque part.

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSsortingng:(NSSsortingng *)ssortingng { if(ssortingng.length > 0) { NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInSsortingng:@"0123456789"]; NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInSsortingng:ssortingng]; BOOL ssortingngIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField]; return ssortingngIsValid; } return YES; } 

Je voulais un champ de texte qui n’autorisait que des entiers. Voici ce que j’ai fini avec (en utilisant les informations d’ici et d’ailleurs):

Créez un formateur de nombres entiers (dans UIApplicationDelegate pour qu’il puisse être réutilisé):

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

Utilisez le filtre dans UITextFieldDelegate:

 @interface MyTableViewController : UITableViewController  { ictAppDelegate *appDelegate; } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementSsortingng:(NSSsortingng *)ssortingng { // Make sure the proposed ssortingng is a number NSNumberFormatter *inf = [appDelegate integerNumberFormatter]; NSSsortingng* proposedSsortingng = [textField.text ssortingngByReplacingCharactersInRange:range withSsortingng:ssortingng]; NSNumber *proposedNumber = [inf numberFromSsortingng:proposedSsortingng]; if (proposedNumber) { // Make sure the proposed number is an integer NSSsortingng *integerSsortingng = [inf ssortingngFromNumber:proposedNumber]; if ([integerSsortingng isEqualToSsortingng:proposedSsortingng]) { // proposed ssortingng is an integer return YES; } } // Warn the user we're rejecting the change AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); return NO; } 

Pas si élégant, mais simple 🙂

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

Acceptez les valeurs décimales dans les champs de texte avec un seul point (.) Fonctionnant avec iPad et iPhone dans Swift 3

  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementSsortingng ssortingng: Ssortingng) -> Bool { let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted let components = ssortingng.components(separatedBy: inverseSet) let filtered = components.joined(separator: "") if filtered == ssortingng { return true } else { if ssortingng == "." { let countdots = textField.text!.components(separatedBy:".").count - 1 if countdots == 0 { return true }else{ if countdots > 0 && ssortingng == "." { return false } else { return true } } }else{ return false } } } 

Pour être plus international (et pas seulement de couleur américaine ;-)), remplacez simplement le code ci-dessus par

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

Cette réponse utilise NSFormatter comme indiqué précédemment. Vérifiez-le:

 @interface NSSsortingng (NSNumber) - (BOOL) isNumberWithLocale:(NSLocale *) ssortingngLocale; - (BOOL) isNumber; - (NSNumber *) getNumber; - (NSNumber *) getNumberWithLocale:(NSLocale*) ssortingngLocale; @end @implementation NSSsortingng (NSNumber) - (BOOL) isNumberWithLocale:(NSLocale *) ssortingngLocale { return [self getNumberWithLocale:ssortingngLocale] != 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*) ssortingngLocale { NSNumberFormatter *formatter = [[ [ NSNumberFormatter alloc ] init ] autorelease]; [formatter setLocale: ssortingngLocale ]; return [ formatter numberFromSsortingng:self ]; } @end 

J’espère que ça aide quelqu’un. =)

  #import "NSSsortingng+Extension.h" //@interface NSSsortingng (Extension) // //- (BOOL) isAnEmail; //- (BOOL) isNumeric; // //@end @implementation NSSsortingng (Extension) - (BOOL) isNumeric { NSSsortingng *emailRegex = @"[0-9]+"; NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex]; return [emailTest evaluateWithObject:self]; // NSSsortingng *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]; // NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInSsortingng: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 ssortingng. It should only appear once for the number to be numeric. // int numberOfOccurances = [[self componentsSeparatedBySsortingng:localDecimalSymbol] count]-1; // return (numberOfOccurances > 1) ? NO : YES; // } // else return NO; } 

Dans Swift 4:

 let formatSsortingng = "12345" if let number = Decimal(ssortingng:formatSsortingng){ print("Ssortingng contains only number") } else{ print("Ssortingng doesn't contains only number") } 

Cela couvre: le contrôle de la partie décimale (y compris le nombre de décimales autorisées), le contrôle copier / coller, les séparateurs internationaux.

Pas:

  1. Assurez-vous que votre contrôleur de vue hérite de UITextFieldDelegate

    la classe MyViewController: UIViewController, UITextFieldDelegate {…

  2. Dans viewDidLoad, définissez votre délégué de contrôle sur self:

    redéfinit func viewDidLoad () {super.viewDidLoad (); yourTextField.delegate = self}

  3. Implémentez la méthode suivante et mettez à jour la constante “decsAllowed” avec la quantité de décimales désirée ou 0 si vous voulez un nombre naturel.

Swift 4

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementSsortingng ssortingng: Ssortingng) -> Bool { let decsAllowed: Int = 2 let candidateText = NSSsortingng(ssortingng: textField.text!).replacingCharacters(in: range, with: ssortingng) let decSeparator: Ssortingng = 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 } 

Si par la suite vous devez convertir en toute sécurité cette chaîne en un nombre, vous pouvez simplement utiliser le transtypage de type Double (yourssortingng) ou Int (yourssortingng), ou le moyen le plus académique:

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