如何从 Xcode 建议之类的列表中搜索(谓词)内容?
How to search(Predicate) content from list like Xcode suggestion?
我想每个人都会注意到 XCode 建议列表。查看此屏幕截图
As per Apple document doesn't provide what expected ouptut.
NSPredicate *inPredicate = [NSPredicate predicateWithFormat: @"attribute CONTAINS[cd] %@", aCollection];
仅提供连续搜索文本。
这可能吗,如何搜索这样的内容?
一个可能的解决方案是为此使用正则表达式。我们只需要在每个字母之间(以及字符串前后)插入 .*
,这意味着 "any character (except for line terminators)"。似乎这就是 XCode 完成时用于搜索的内容。
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];
要播放的示例,请在之前插入:
NSString *keyToFilter = @"attribute";
NSArray *array = @[@{keyToFilter:@"UITextField"}, @{keyToFilter:@"nsarray"}, @{keyToFilter:@"uitf"}];
NSString *searchString = @"uitf";
紧接着:
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
NSLog(@"SearchString: %@\nFiltered: %@", searchString, ([filtered count]?[filtered valueForKey:keyToFilter]:@"NO RESULT"));
输出:
$>SearchString: uitf
Filtered: (
UITextField,
uitf
)
构造字母数组的代码来自here。可以使用不同的解决方案来创建 pattern
,它可能不是最好的,但它是可行的。
奖金:
为了好玩(我对如何做很感兴趣),一种可能的方法来为列表着色(我制作了一个 NSAttributedString
的数组)以适应(未完全测试或没有错误):
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];
}
我想每个人都会注意到 XCode 建议列表。查看此屏幕截图
As per Apple document doesn't provide what expected ouptut.
NSPredicate *inPredicate = [NSPredicate predicateWithFormat: @"attribute CONTAINS[cd] %@", aCollection];
仅提供连续搜索文本。
这可能吗,如何搜索这样的内容?
一个可能的解决方案是为此使用正则表达式。我们只需要在每个字母之间(以及字符串前后)插入 .*
,这意味着 "any character (except for line terminators)"。似乎这就是 XCode 完成时用于搜索的内容。
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];
要播放的示例,请在之前插入:
NSString *keyToFilter = @"attribute";
NSArray *array = @[@{keyToFilter:@"UITextField"}, @{keyToFilter:@"nsarray"}, @{keyToFilter:@"uitf"}];
NSString *searchString = @"uitf";
紧接着:
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
NSLog(@"SearchString: %@\nFiltered: %@", searchString, ([filtered count]?[filtered valueForKey:keyToFilter]:@"NO RESULT"));
输出:
$>SearchString: uitf
Filtered: (
UITextField,
uitf
)
构造字母数组的代码来自here。可以使用不同的解决方案来创建 pattern
,它可能不是最好的,但它是可行的。
奖金:
为了好玩(我对如何做很感兴趣),一种可能的方法来为列表着色(我制作了一个 NSAttributedString
的数组)以适应(未完全测试或没有错误):
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];
}