Iphone 如何优化此基于核心数据的搜索?

Iphone 如何优化此基于核心数据的搜索?,iphone,objective-c,ios,optimization,core-data,Iphone,Objective C,Ios,Optimization,Core Data,我正在尝试在我的应用程序中实现搜索。有两个核心数据实体,“Tag”和“DvarTorah”。标记只有一个字符串。“德瓦托拉”有标题、文本内容和一些其他属性。我正试图找出快速搜索它们的最佳方法。这款应用附带了大约1200个德瓦托拉实体,甚至更多的标签。现在,当我的搜索视图控制器调用viewDidLoad时,我加载了一个NSFetchedResultsController。然后,当用户在搜索框中键入内容或更改范围时,我调用一个方法,该方法同时接收范围栏值和搜索词,并过滤我的对象数组。这看起来是这样的

我正在尝试在我的应用程序中实现搜索。有两个核心数据实体,“Tag”和“DvarTorah”。标记只有一个字符串。“德瓦托拉”有标题、文本内容和一些其他属性。我正试图找出快速搜索它们的最佳方法。这款应用附带了大约1200个德瓦托拉实体,甚至更多的标签。现在,当我的搜索视图控制器调用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]];

}
Edit2:

不再复制阵列,仍然很慢:

- (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]];
}

这里有很多东西会占用CPU周期和内存:

首先,您正在制作从
NSFetchedResultsController
获取的结果的可变副本。为什么?

第二,在上述结果的构造中为..使用一个
,并分别调用
-[NSPredicate evaluateWithObject:
。您可以修改谓词搜索字符串以使用
-[NSArray filteredarrayingpredicate:
,这很可能比您的方法更快

第三,您的
谓词
变量存在一个相当微妙的问题-您总是在开始时将其重新分配给自动释放的空变量以外的其他变量。将默认值设置为
nil

第四,正如您所提到的,您的谓词字符串效率很低。 我认为你需要做一些叫做索引的事情

有关使用核心数据进行全文搜索的更多信息:


四个版本的速度是否都一样慢?您筛选的结果集有多大?你能用其他东西而不是contains吗?@DavidRönnqvist-结果集大约有1200个对象。也许我完全误解了UISearchResultsController。。。至于比较慢的问题,我是用肉眼分析,而不是用工具,所以我不确定。对我来说似乎差不多。我可以在NSFetchedResultsController上调用
FilteredArrayingPredicate
?如果不是,我可以将其用作类方法吗>如果不是,我需要额外的数组。查看我的更新代码。是的,这是我最大的问题。