Vérifier qu'une entrée à UITextField est numérique seulement
comment valider la chaîne de caractères entrée dans un UITextField
? Je veux vérifier que la chaîne est numérique, y compris les points décimaux.
22 réponses
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 rend le texte rouge lorsqu'il est invalide.
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]];
}
}
Vous pouvez le faire en quelques lignes comme ceci:
BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];
if (!valid) // Not numeric
-- ceci est pour valider l'entrée est des caractères numériques seulement. Consultez la documentation pour NSCharacterSet
pour les autres options. Vous pouvez utiliser characterSetWithCharactersInString pour spécifier tout ensemble de caractères d'entrée valides.
il y a plusieurs façons de faire cela:
- utiliser le numéro Nsnumberformatter's number fromstring: method. Ceci retournera un nombre NSN s'il peut analyser la chaîne correctement, ou
nil
s'il ne peut pas. - Use NSScanner
- rayer tout caractère non numérique et voir si la chaîne de caractères correspond toujours
- utiliser une expression régulière
IMO, en utilisant quelque chose comme -[NSString doubleValue]
ne serait pas la meilleure option parce que les deux @"0.0"
et @"abc"
auront une valeur double de 0. Les méthodes *value toutes retournent 0 si elles ne sont pas capables de 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 il prend locale dans compte (ie, le nombre @"1,23"
en Europe, contre @"1.23"
aux Etats-Unis).
si vous voulez qu'un utilisateur soit seulement autorisé à entrer des chiffres, vous pouvez faire votre ViewController implémenter une partie de UITextFieldDelegate et définir cette méthode:
- (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];
}
il y a probablement des moyens plus efficaces, mais je trouve que c'est une jolie pratique . Et la méthode doit être facilement adaptable à la validation des doubles ou autre: il suffit d'utiliser scanDouble: ou similaire.
#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;
}
voici quelques-uns de ceux qui combinent la réponse de Peter Lewis ci-dessus ( vérifier qu'une entrée à UITextField est numérique seulement ) avec 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]
pour le test entier ce sera:
- (BOOL) isIntegerNumber: (NSString*)input
{
return [input integerValue] != 0 || [input isEqualToString:@"0"];
}
vous pouvez utiliser la double valeur de votre chaîne comme
NSString *string=@"1.22";
double a=[string doubleValue];
je pense que cela va retourner un as 0.0 si la chaîne est invalide (il pourrait jeter une exception, dans ce cas, vous pouvez juste l'attraper, les docs disent 0.0 tho). en savoir plus ici
Hi avait exactement le même problème et je ne vois pas la réponse que j'ai utilisé posté, donc 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 j'ai sélectionné L'événement D'édition modifié. 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 personnage défini pour inclure le caractère décimal / période et les nombres. Sépare fondamentalement la chaîne sur les caractères invalides, puis les rejoint avec la chaîne vide.
- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender {
NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet;
sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""];
}
crédits: supprimer tous les numéros sauf ceux de la NSString
"en retard au jeu mais voici une petite catégorie pratique que j'utilise qui explique les décimales et le symbole local utilisé pour elle. lien vers son gist ici
@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
IMO le meilleur moyen d'atteindre votre objectif est d'afficher un clavier numérique plutôt que le clavier normal. Cela restreint les clés qui sont disponibles à l'utilisateur. Cela réduit le besoin de faire de la validation, et plus important encore, il empêche l'utilisateur de faire une erreur. Le pavé numérique est également beaucoup plus agréable pour entrer des nombres parce que les clés sont beaucoup plus grandes.
dans interface builder sélectionnez L'UITextField, allez à L'Inspecteur des attributs et changez le "Type de clavier "à"bloc décimal".
qui fera ressembler le clavier à ceci:
la seule chose à faire est de s'assurer que l'utilisateur n'entre pas deux décimales. Tu peux faire ça pendant qu'ils éditent. Ajoutez le code suivant à votre contrôleur de vue. Ce code supprime une deuxième décimale la place dès qu'il est entré. Il apparaît à l'utilisateur comme si la 2ème décimale n'est jamais apparu dans la première place.
- (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;
}
}
vieux fil, mais il est intéressant de mentionner que Apple a introduit NSRegularExpression
dans iOS 4.0. (En prenant l'expression régulière à partir de Pierre de réponse)
// 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!
}
je suggère de stocker l'instance NSRegularExpression
quelque part.
- (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;
}
je voulais un champ de texte qui ne permettait entiers. Voici ce que j'ai fini par dire (en utilisant des informations d'ici et d'ailleurs):
Créer un nombre entier formateur (en UIApplicationDelegate de sorte qu'il peut ê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;
}
utiliser un filtre dans 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;
}
pas si élégant, mais simple:)
- (BOOL) isNumber: (NSString*)input
{
return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"];
}
Accepter les valeurs décimales dans les champs de texte avec un seul (.) dot travaille avec iPad et iPhone dans 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
}
}
}
Pour être plus à l'international (et pas seulement NOUS, de couleur ;-) ) il suffit de remplacer dans le code ci-dessus par
-(NSNumber *) getNumber
{
NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
cette réponse utilise NSFormatter comme dit précédemment. Check it out:
@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
j'espère que ça aidera quelqu'un. = )
#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;
}
Dans Swift 4:
let formatString = "12345"
if let number = Decimal(string:formatString){
print("String contains only number")
}
else{
print("String doesn't contains only number")
}
couvre: le contrôle de la partie décimale (y compris le nombre de décimales autorisées), le contrôle de la copie/pâte, les séparateurs internationaux.
Suit:
-
assurez-vous que votre contrôleur de vue hérite de UITextFieldDelegate
class MyViewController: UIViewController, UITextFieldDelegate {...
-
Dans le viewDidLoad, définissez votre contrôle délégué à moi-même:
outrepasser func viewDidLoad() { super.viewDidLoad(); yourTextField.delegate = self }
-
implémentez la méthode suivante et mettez à jour la constante" decsAllowed " avec la quantité désirée de décimales ou 0 si vous voulez un nombre naturel.
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
}
si après vous avez besoin de convertir en toute sécurité cette chaîne en un nombre, vous pouvez juste utiliser Double(votre corde) ou Int (votre corde) cast, ou la manière plus académique:
let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!