【发布时间】:2011-12-11 14:38:32
【问题描述】:
我正在尝试在我的应用中实现搜索。有两个核心数据实体,“Tag”和“DvarTorah”。一个标签只有一个字符串。 “DvarTorah”具有标题、文本内容和其他一些属性。我正在尝试找出快速搜索它们的最佳方法。该应用程序附带大约 1200 个 DvarTorah 实体,甚至更多标签。现在,当我的搜索视图控制器调用 viewDidLoad 时,我加载了一个 NSFetchedResultsController。然后,当用户在搜索框中键入或更改范围时,我调用一个方法,该方法同时接受范围栏值和搜索词,并过滤我的对象数组。看起来是这样的:
- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{
if ([searchString isEqualToString:@""]) {
return;
}
NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];
if (self.filteredArray == nil){
self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
}
[filteredArray removeAllObjects];
NSPredicate *predicate = [[[NSPredicate alloc] init] autorelease];
if (scopeIndex == 0) {
predicate = [NSPredicate predicateWithFormat:@"dvarTorahTitle CONTAINS[cd] %@", searchString];
}else if (scopeIndex == 1) {
predicate = [NSPredicate predicateWithFormat:@"searchableContent CONTAINS[cd] %@", [searchString canonicalString]];
}else if (scopeIndex == 2){
predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
}else{
predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (searchableContent CONTAINS[cd] %@)", searchString,searchString,searchString];
}
for (DvarTorah *dvarTorah in unfilteredResults) {
if ([predicate evaluateWithObject:dvarTorah]) {
[self.filteredArray addObject:dvarTorah];
}
}
[unfilteredResults release];
}
问题是我的搜索方法非常慢。我知道 CONTAINS 可能是罪魁祸首,但即使在存储了内容的规范版本(作为 searchableContent)并尝试进一步优化之后,搜索速度也非常慢。我怎样才能让它更快?
编辑:
根据 Jacob 的初步建议,这是我的新方法:
if ([searchString isEqualToString:@""]) {
return;
}
if (self.filteredArray == nil) {
self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
}
[filteredArray removeAllObjects];
NSPredicate *predicate = nil;
if (scopeIndex == 0) {
predicate = [NSPredicate predicateWithFormat:@"dvarTorahTitle CONTAINS[cd] %@", searchString];
}else if (scopeIndex == 1) {
predicate = [NSPredicate predicateWithFormat:@"searchableContent CONTAINS[cd] %@", [searchString canonicalString]];
}else if (scopeIndex == 2){
predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
}else{
predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (searchableContent CONTAINS[cd] %@)", searchString,searchString,searchString];
}
[self.filteredArray addObjectsFromArray:[[[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy] filteredArrayUsingPredicate:predicate]];
}
编辑2:
不再复制数组,仍然很慢:
- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{
if ([searchString isEqualToString:@""]) {
return;
}
if (self.filteredArray == nil) {
self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
}
[filteredArray removeAllObjects];
NSPredicate *predicate = nil;
if (scopeIndex == 0) {
predicate = [NSPredicate predicateWithFormat:@"dvarTorahTitle CONTAINS[cd] %@", searchString];
}else if (scopeIndex == 1) {
predicate = [NSPredicate predicateWithFormat:@"searchableContent CONTAINS[cd] %@", [searchString canonicalString]];
}else if (scopeIndex == 2){
predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
}else{
predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (searchableContent CONTAINS[cd] %@)", searchString,searchString,searchString];
}
[self.filteredArray addObjectsFromArray:[[[[self.fetchedResultsController sections] objectAtIndex:0] objects] filteredArrayUsingPredicate:predicate]];
}
【问题讨论】:
-
四个版本都一样慢吗?您要过滤的结果集有多大?你能不使用包含以外的东西吗?
-
@DavidRönnqvist - 结果集大约有 1200 个对象。也许我完全误解了 UISearchResultsController ...就相对缓慢而言,我是通过眼睛进行分析,而不是使用工具,所以我不确定。对我来说似乎差不多。
标签: iphone objective-c ios optimization core-data