如何改进NSFetchedResultsController performFetch:性能?

Yoz*_* W. 3 uisearchdisplaycontroller nsfetchedresultscontroller ios

我在数据库中只有3237条记录,我使用UISearchDisplayController和NSFetchedResultsController进行搜索.但是当我为搜索键入关键字时,它非常慢:

2012-06-26 10:26:25.264 KYBD[3863:707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZARTICLEPARTCHINESE, t0.ZARTICLEPARTENGLISH, t0.ZARTICLEPARTNUMBER, t0.ZARTICLE FROM ZARTICLECONTENT t0 LEFT OUTER JOIN ZARTICLES t1 ON t0.ZARTICLE = t1.Z_PK WHERE ( NSCoreDataStringSearch( t0.ZARTICLEPARTENGLISH, ?, 257, 0) OR  NSCoreDataStringSearch( t0.ZARTICLEPARTCHINESE, ?, 257, 0)) ORDER BY t1.ZARTICLETITLE, t0.ZARTICLEPARTNUMBER
2012-06-26 10:26:26.438 KYBD[3863:707] CoreData: annotation: sql connection fetch time: 0.5325s
2012-06-26 10:26:26.446 KYBD[3863:707] CoreData: annotation: total fetch execution time: 1.1821s for 2549 rows.
2012-06-26 10:26:26.489 KYBD[3863:707] CoreData: sql: SELECT  t1.ZARTICLETITLE, COUNT (DISTINCT  t0.Z_PK) FROM ZARTICLECONTENT t0 LEFT OUTER JOIN ZARTICLES t1 ON t0.ZARTICLE = t1.Z_PK WHERE ( NSCoreDataStringSearch( t0.ZARTICLEPARTENGLISH, ?, 257, 0) OR  NSCoreDataStringSearch( t0.ZARTICLEPARTCHINESE, ?, 257, 0)) GROUP BY  t1.ZARTICLETITLE ORDER BY t1.ZARTICLETITLE
2012-06-26 10:26:26.874 KYBD[3863:707] CoreData: annotation: sql connection fetch time: 0.3733s
2012-06-26 10:26:26.879 KYBD[3863:707] CoreData: annotation: total fetch execution time: 0.3904s for 100 rows.
Run Code Online (Sandbox Code Playgroud)

我的NSFetchedResultsController代码:

- (NSFetchedResultsController *)fetchedResultsController {
    if (!_fetchedResultsController) {
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        request.entity = [NSEntityDescription entityForName:@"ArticleContent" inManagedObjectContext:self.managedObjectContext];
        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"article.articleTitle" ascending:YES];
        NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"articlePartNumber" ascending:YES];
        request.sortDescriptors = [NSArray arrayWithObjects:sort, sort2, nil];
        request.predicate = nil;

        [NSFetchedResultsController deleteCacheWithName:@"searchResults"];
        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"article.articleTitle" cacheName:@"searchResults"];
    }

    return _fetchedResultsController;
}
Run Code Online (Sandbox Code Playgroud)

和搜索代码:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    if ([searchString length] > 0) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self.fetchedResultsController selector:@selector(performFetch:) object:nil];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"articlePartEnglish CONTAINS[c] %@ OR articlePartChinese CONTAINS[c] %@", searchString, searchString];
        self.fetchedResultsController.fetchRequest.predicate = predicate;
        [NSFetchedResultsController deleteCacheWithName:@"searchResults"];
        [self.fetchedResultsController performFetch:nil];

    }

    return YES; 
}
Run Code Online (Sandbox Code Playgroud)

有什么问题吗?我怎样才能提高性能?最好的祝福.

ric*_*ter 7

使用CONTAINS谓词很慢,特别是如果它不区分大小写.使用两个使它更慢.

Apple通过不实际进行全文搜索,使其应用​​程序中的"全文"搜索看起来很快.他们的大多数应用程序使用前缀搜索,依赖于如果您正在搜索"Frank"的概念,那么您不会输入"ran".此外,它们标准化属性并进行基于排序的搜索:例如,如果您拥有firstName内容类似"François"的normalizedFirstName属性,则会创建一个丢失案例和变音符号("francois")的派生属性.然后你搜索"franc"获得谓词:

normalizedFirstName >= "franc" AND normalizedFirstName < "frand"
Run Code Online (Sandbox Code Playgroud)

这个谓词要快得多.

如果您的属性可以包含多字符串,并且您希望对字符串上的任何单词执行类似的前缀匹配,则可以为关键字创建相关实体,并使用子查询来匹配关键字适合谓词的实体.

有关详细信息,请参阅DerivedProperty示例代码和/或WWDC 2010会话137的视频(均在developer.apple.com上).