You can try two options for defining the predicate. A format string and a block. Here is a bit of code that demonstrates both. I've played a bit with both and can share that the performance is the same. I've only had the patience to run it with a max value of INT32_MAX/2 (a lot of items).
Here goes. Hope this clarifies and helps:
NSString* searchString = @"AB0";
NSUInteger capacity = 1000000;
NSMutableArray* array = [NSMutableArray array];
NSLog(@"Fillling array with %lu UUIDS. Be patient.", (unsigned long)capacity);
NSUInteger batch = 0;
for ( NSUInteger i = 0; i < capacity; i++ ) {
[array setObject:[[NSUUID UUID] UUIDString] atIndexedSubscript:i];
if (i != 0 && i % (capacity / 10) == 0 ) {
NSLog(@"Completed %lu%%", (unsigned long)++batch * 10);
}
}
NSLog(@"Done.");
NSPredicate* formatPredicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@ AND SELF.length > 3", searchString];
NSLog(@"Filtering with predicate: %@", formatPredicate);
NSArray* formatArray = [array filteredArrayUsingPredicate:formatPredicate];
NSLog(@"Got %lu results.", formatArray.count);
NSPredicate* blockPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSString* theString = evaluatedObject;
return theString.length > 3 && [theString rangeOfString:searchString].location != NSNotFound;
}];
NSLog(@"Filtering with predicate: %@", blockPredicate);
NSArray* blockArray = [array filteredArrayUsingPredicate:blockPredicate];
NSLog(@"Got %lu results.", blockArray.count);
PS: I wouldn't run this on a phone if you are using big numbers line INT32_MAX :)