Как проверить, содержит ли строка только буквенно-цифровые символы в objective C?


Я работаю над небольшим проектом iphone, и мне нужно будет проверить, содержит ли Введенное имя пользователя только буквенно-цифровые символы? (A-Z, a-z, 0-9. Как бы я это проверил?

8 46

8 ответов:

Если вы не хотите использовать библиотеку регулярных выражений для этой задачи...

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

Это будет работать:

@implementation NSString (alphaOnly)

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

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

@end

Вы можете использовать эту библиотеку регулярных выражений для ObjectiveC. Используйте следующее регулярное выражение для сопоставления:

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

Ответы на основе NSCharacterSet не дают результатов, которые можно было бы ожидать для японского текста и т. д., Часто утверждая, что они содержат буквенно - цифровые символы-выполняемый тест сводится к "существуют ли только буквы или цифры", а японские (и т. д.) символы считаются "буквами".

Если вы пытаетесь проверить латинские символы на иностранном языке (например. Японский), то ответ из " Как определить, является ли NSString Латинской основой? " может помочь:

BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding];

NSASCIIStringEncoding мог бы также используется вместо NSISOLatin1StringEncoding для дальнейшего ограничения допустимых символов. Вы также можете протестировать использование NSCharacterSet впоследствии, чтобы исключить специальные символы, такие как !, #, прием.

Я провел довольно обширное тестирование производительности, и есть несколько соображений, которые следует учитывать при выборе способа проверки ваших буквенно-цифровых строк. Во-первых, конечно, вы можете даже не заботиться о производительности. Если ваше приложение редко проверяет строки или, возможно, даже делает это только один раз, любой метод, который дает вам желаемое поведение, подходит. Кроме того, вот мои результаты работы.

Для пользовательских наборов символов (скажем, буквенно-цифровых символов, без Unicode символов или меток), это самый быстрый для начального запуска:

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

return [result isEqualToString:@""];

Если вы в порядке, используя предварительно вычисленный набор символов, такой как [NSCharacterSet alphanumericCharacterSet] , то это было быстрее всего:

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

return (range.location == NSNotFound);

Кэширование набора символов в статической переменной с помощью dispatch_once может немного помочь, если вы будете выполнять эти проверки повторно. В этом случае, если вы уверены, что можете поглотить начальное время компиляции, использование регулярного выражения на самом деле оказывается самым быстрым для пользовательских наборов символов:

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);

Если вы этого не сделаете если вы хотите использовать регулярное выражение, версия пользовательского набора кэшированного rangeOfCharacterFromSet граничит с кэшированным stringByTrimmingCharactersInCharacterSet: методом:

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);

Для предварительно вычисленных множеств кэшированный метод rangeOfCharacterFromSet: снова был самым быстрым:

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);

И для информации каждого, метод isSupersetOfSet: был самым медленным, независимо от того, кэширован он или нет. Похоже, что isSupersetOfSet: довольно медленно.

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

return [alphanumericSet isSupersetOfSet:stringSet];

Я не проводил никакого тестирования базовых функций CFCharacterSet.

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

Обладает гибкостью для добавления / вычитания новых символов, таких как пробелы

P. S Этот метод можно скопировать / вставить в категорию NSString

Мне очень нравится RegexKit Lite фреймворк. Он использует библиотеку регулярных выражений ICU, которая уже включена в OSX и безопасна для Юникода.

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

Вы можете использовать возможности регулярного выражения NSString, представленные в iOS 3.2:

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