I have done some pretty extensive performance testing, and there are a few considerations to consider when choosing a method for checking alphanumeric strings. First, of course, you may not even care about performance. If your application rarely checks strings, or perhaps even does it once, any method that gives you the behavior you want is fine. In addition, here are my work results.
For custom character sets (e.g. alphanumeric characters, without Unicode characters or labels) this is the fastest to get started:
NSCharacterSet *alphanumericSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"]; NSString *result = [self stringByTrimmingCharactersInSet:alphanumericSet]; return [result isEqualToString:@""];
If you agree using a pre-computed character set, such as [NSCharacterSet alphanumericCharacterSet] , this was the fastest:
NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet]; alphanumericSet = alphanumericSet.invertedSet; NSRange range = [self rangeOfCharacterFromSet:alphanumericSet]; return (range.location == NSNotFound);
Caching a character set in a static variable using dispatch_once may help a little if you re-run these checks. In this case, if you are sure that you can understand the initial compilation time, using a regular expression is actually the fastest for custom character sets:
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);
If you do not want to use the regular expression, the custom version of the cached rangeOfCharacterFromSet limits the caching method 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);
For pre-computed sets, the rangeOfCharacterFromSet: caching method was again the fastest:
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);
And for each information, the isSupersetOfSet: method was the slowest, whether in the cache or not. Looks like isSupersetOfSet: pretty slow.
NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:self]; NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet]; return [alphanumericSet isSupersetOfSet:stringSet];
I have not tested the basic functions of CFCharacterSet.