带有核心数据的慢速 UISearchDisplayController
Slow UISearchDisplayController with Core Data
我有一个 TableViewController,使用 NSFetchedResultsController 显示来自 Core Data 的大约 40 000 行。
我使用 UISearchDisplayController 实现了实时搜索(支持 IOS 7)。
可以用,但是搜索时在键盘上打字速度很慢...
如果有人能指出正确的方向并告诉我哪里可能出错,我将不胜感激。
这是我的 TableViewController 中的 UISearchResultsUpdating 部分
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
ItemSearchScope scopeKey = controller.searchBar.selectedScopeButtonIndex;
[self searchForText:searchString scope:scopeKey];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
NSString *searchString = controller.searchBar.text;
[self searchForText:searchString scope:searchOption];
return YES;
}
- (void)searchForText:(NSString *)searchText scope:(ItemSearchScope)scopeOption
{
if (self.managedObjectContext)
{
NSString *predicateFormat = @"%K CONTAINS[cd] %@";
NSString *searchAttribute1 = @"attribute1";
NSString *searchAttribute2 = @"attribute2";
NSString *searchAttribute3 = @"attribute3";
if (scopeOption == searchScopeDebut) {
predicateFormat = @"%K BEGINSWITH[cd] %@";
}
if (scopeOption == searchScopeFin) {
predicateFormat = @"%K ENDSWITH[cd] %@";
}
NSPredicate *p1 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute1, searchText];
NSPredicate *p2 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute2, searchText];
NSPredicate *p3 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute3, searchText];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[p1, p2, p3]];
[self.searchFetchRequest setPredicate:predicate];
NSError *error = nil;
self.filteredList = [self.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&error];
if (error)
{
NSLog(@"searchFetchRequest failed: %@",[error localizedDescription]);
}
}
}
我最终使用 NSTimer 来延迟 shouldReloadTableForSearchString 方法。仅当用户停止键入键盘 2 秒时,才会触发 searchTimerPopped 选择器。
@property (nonatomic, retain) NSTimer *searchTimer;
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if (self.searchTimer) {
[self.searchTimer invalidate];
self.searchTimer = nil;
}
self.searchTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(searchTimerPopped:) userInfo:searchString repeats:FALSE];
return NO;
}
- (void)searchTimerPopped:(NSTimer *)timer {
NSString *searchString = [timer userInfo];
ItemSearchScope scopeKey = self.searchDisplayController.searchBar.selectedScopeButtonIndex;
[self searchForText:searchString scope:scopeKey];
[self.searchDisplayController.searchResultsTableView reloadData];
}
我有一个 TableViewController,使用 NSFetchedResultsController 显示来自 Core Data 的大约 40 000 行。
我使用 UISearchDisplayController 实现了实时搜索(支持 IOS 7)。 可以用,但是搜索时在键盘上打字速度很慢...
如果有人能指出正确的方向并告诉我哪里可能出错,我将不胜感激。
这是我的 TableViewController 中的 UISearchResultsUpdating 部分
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
ItemSearchScope scopeKey = controller.searchBar.selectedScopeButtonIndex;
[self searchForText:searchString scope:scopeKey];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
NSString *searchString = controller.searchBar.text;
[self searchForText:searchString scope:searchOption];
return YES;
}
- (void)searchForText:(NSString *)searchText scope:(ItemSearchScope)scopeOption
{
if (self.managedObjectContext)
{
NSString *predicateFormat = @"%K CONTAINS[cd] %@";
NSString *searchAttribute1 = @"attribute1";
NSString *searchAttribute2 = @"attribute2";
NSString *searchAttribute3 = @"attribute3";
if (scopeOption == searchScopeDebut) {
predicateFormat = @"%K BEGINSWITH[cd] %@";
}
if (scopeOption == searchScopeFin) {
predicateFormat = @"%K ENDSWITH[cd] %@";
}
NSPredicate *p1 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute1, searchText];
NSPredicate *p2 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute2, searchText];
NSPredicate *p3 = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute3, searchText];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[p1, p2, p3]];
[self.searchFetchRequest setPredicate:predicate];
NSError *error = nil;
self.filteredList = [self.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&error];
if (error)
{
NSLog(@"searchFetchRequest failed: %@",[error localizedDescription]);
}
}
}
我最终使用 NSTimer 来延迟 shouldReloadTableForSearchString 方法。仅当用户停止键入键盘 2 秒时,才会触发 searchTimerPopped 选择器。
@property (nonatomic, retain) NSTimer *searchTimer;
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if (self.searchTimer) {
[self.searchTimer invalidate];
self.searchTimer = nil;
}
self.searchTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(searchTimerPopped:) userInfo:searchString repeats:FALSE];
return NO;
}
- (void)searchTimerPopped:(NSTimer *)timer {
NSString *searchString = [timer userInfo];
ItemSearchScope scopeKey = self.searchDisplayController.searchBar.selectedScopeButtonIndex;
[self searchForText:searchString scope:scopeKey];
[self.searchDisplayController.searchResultsTableView reloadData];
}