A possible solution, is to use a Regular Expression for that. We just need to insert .*
between each letter (and before and after the string) which means "any character (except for line terminators)". It seems that's what's used for the search on XCode completion.
NSMutableArray *letters = [[NSMutableArray alloc] init];
[searchString enumerateSubstringsInRange:NSMakeRange(0, [searchString length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
[letters addObject:substring];
}];
NSMutableString *pattern = [[NSMutableString alloc] initWithString:@".*"];
[pattern appendString:[letters componentsJoinedByString:@".*"]];
[pattern appendString:@".*"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.%K MATCHES[C] %@", keyToFilter, pattern];
Sample to play, insert just before:
NSString *keyToFilter = @"attribute";
NSArray *array = @[@{keyToFilter:@"UITextField"}, @{keyToFilter:@"nsarray"}, @{keyToFilter:@"uitf"}];
NSString *searchString = @"uitf";
and just after:
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
NSLog(@"SearchString: %@
Filtered: %@", searchString, ([filtered count]?[filtered valueForKey:keyToFilter]:@"NO RESULT"));
Output:
$>SearchString: uitf
Filtered: (
UITextField,
uitf
)
The code taken for construction the array of letters is from here. Different solutions could have been used to create pattern
, it's maybe not the best one, but it's a working one.
Bonus:
And for fun (I was intriguing on how doing it), a possible way to color the list (I made an array of NSAttributedString
) to adapt (not fully tested or errors free):
NSMutableArray *filteredColored = [[NSMutableArray alloc] init];
for (NSDictionary *aDict in filtered) //or for (MyObjectClass *myObject in filtered)
{
NSString *aFilteredValue = aDict[keyToFilter]; //or NSString *aFilteredValue = [myObject attribute]
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:aFilteredValue attributes:@{}];
NSInteger currentIndex = 0;
for (NSString *aLetter in letters)
{
NSRange rangeFound = [aFilteredValue rangeOfString:aLetter
options:NSCaseInsensitiveSearch
range:NSMakeRange(currentIndex, [aFilteredValue length]-currentIndex)];
if (rangeFound.location != NSNotFound)
{
currentIndex = rangeFound.location+rangeFound.length;
[attr addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:rangeFound];
}
}
[filteredColored addObject:attr];
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…