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

StackOverflow https://stackoverflow.com/questions/1671605

Вопрос

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

Это было полезно?

Решение

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

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

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

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

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

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

BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding];

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

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

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

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

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

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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top