web-dev-qa-db-fra.com

Comment vérifier si une chaîne ne contient que des caractères alphanumériques dans l'objectif C?

Je travaille sur un petit projet iphone et il me faudrait vérifier si le nom d'utilisateur entré contient uniquement des caractères alphanumériques? (A-Z, a-z, 0-9. Comment pourrais-je vérifier cela?

46
Cheng Lai

Si vous ne souhaitez pas importer de bibliothèque regex pour cette tâche particulière ...

NSString *str = @"aA09";
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet];
BOOL valid = [[str stringByTrimmingCharactersInSet:alphaSet] isEqualToString:@""]; 
86
Jason Harwig

Cela fonctionnera:

@implementation NSString (alphaOnly)

- (BOOL) isAlphaNumeric
{
    NSCharacterSet *unwantedCharacters = 
       [[NSCharacterSet alphanumericCharacterSet] invertedSet];

    return ([self rangeOfCharacterFromSet:unwantedCharacters].location == NSNotFound);
}

@end
61
NSResponder

Vous pouvez utiliser cette bibliothèque d’expressions régulières pour ObjectiveC. Utilisez les expressions régulières suivantes:

^[a-zA-Z0-9]*$
9
Soviut

Les réponses basées sur NSCharacterSet ne donnent pas les résultats escomptés pour le texte japonais, etc., affirmant souvent qu'elles contiennent des caractères alphanumériques. 'Des lettres'.

Si vous essayez de vérifier les caractères latins par rapport à une langue étrangère (par exemple, le japonais), la réponse de " Comment déterminer si une chaîne NSString est basée sur le latin? " Peut aider:

BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding];

NSASCIIStringEncoding peut également être utilisé à la place de NSISOLatin1StringEncoding pour restreindre davantage les caractères valides. Vous pouvez également tester ensuite l'utilisation de NSCharacterSet pour exclure les caractères spéciaux tels que!, #, Etc.

8
JosephH

J'ai effectué des tests de performances assez poussés et plusieurs considérations doivent être prises en compte lors du choix de la validation des chaînes alphanumériques. Tout d’abord, bien sûr, vous ne vous souciez peut-être même pas de la performance. Si votre application valide rarement les chaînes, ou peut-être même une seule fois, quelle que soit la méthode qui vous donne le comportement que vous voulez, c'est bien. Au-delà de cela, voici mes résultats de performance.

Pour les jeux de caractères personnalisés (par exemple, les caractères alphanumériques, sans caractères Unicode ni marques), ceci est le plus rapide pour une exécution initiale:

NSCharacterSet *alphanumericSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"];
NSString *result = [self stringByTrimmingCharactersInSet:alphanumericSet];

return [result isEqualToString:@""];

Si vous utilisez un jeu de caractères précalculé tel que [NSCharacterSet alphanumericCharacterSet], c'est le plus rapide:

NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
alphanumericSet = alphanumericSet.invertedSet;
NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

La mise en cache du jeu de caractères dans une variable statique à l'aide de dispatch_once peut s'avérer très utile si vous exécutez ces validations à plusieurs reprises. Dans ce cas, si vous êtes certain de pouvoir absorber le temps de compilation initial, utiliser une expression régulière s'avère le plus rapide pour les jeux de caractères personnalisés:

static NSRegularExpression *alphanumericRegex;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericRegex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z0-9]*$" options:NSRegularExpressionCaseInsensitive error:nil];
});
NSUInteger numberOfMatches = [alphanumericRegex numberOfMatchesInString:self options:0 range:NSMakeRange(0, self.length)];

return (numberOfMatches == 1);

Si vous ne souhaitez pas utiliser l'expression régulière, la version définie personnalisée de la variable rangeOfCharacterFromSet mise en cache délimite la méthode stringByTrimmingCharactersInCharacterSet: mise en cache:

static NSCharacterSet *alphanumericSet;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"];
    alphanumericSet = alphanumericSet.invertedSet;
});

NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

Pour les ensembles précalculés, la méthode rangeOfCharacterFromSet: en cache était à nouveau la plus rapide:

static NSCharacterSet *alphanumericSet;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
    alphanumericSet = alphanumericSet.invertedSet;
});

NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

Et pour l’information de tous, la méthode isSupersetOfSet: était la plus lente, qu’elle soit mise en cache ou non. On dirait que isSupersetOfSet: est assez lent.

NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:self];
NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];

return [alphanumericSet isSupersetOfSet:stringSet];

Je n'ai pas testé les fonctions sous-jacentes de CFCharacterSet.

5
Jon Shier
- (BOOL)isAlphaNumeric
{
     NSCharacterSet *s = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'. "];
     s = [s invertedSet];
     NSRange r = [self rangeOfCharacterFromSet:s];
     if (r.location == NSNotFound) {
         return NO;
     } else {
       return YES;
    }
}

A la possibilité d'ajouter/de soustraire de nouveaux caractères tels que des espaces

P.S Cette méthode peut être copier/coller dans la catégorie NSString

3
carelesslyChoosy

J'aime beaucoup le RegexKitLite Framework. Il utilise la bibliothèque de regex ICU, qui est déjà incluse dans OSX et qui est sécurisée pour Unicode.

NSString *str = @"testString";
[str isMatchedByRegex:@"^[a-zA-Z0-9]*$"]; // strict ASCII-match
[str isMatchedByRegex:@"^[\p{L}\p{N}]*$"]; // unicode letters and numbers match
2
Adrian

Vous pouvez utiliser les capacités d'expression régulière NSString introduites dans iOS 3.2:

- (BOOL)isAlphanumeric:(NSString *)string {
    return [string rangeOfString:@"^[a-zA-Z0-9]+$" options:NSRegularExpressionSearch].location != NSNotFound;
}
0
Rob