UISearchDisplayController和搜索大量数据的性能

时间:2010-04-12 14:47:03

标签: iphone performance multithreading uisearchdisplaycontroller

我正在尝试找出使用UISearchDisplayController执行快速搜索的最佳方式。

我有一个包含超过36000个条目的plist文件。我在字典中加载此文件,然后在此字典中执行搜索。它有效,但它有点慢,每次触摸事件之间都有延迟。我想要一个自动完成效果,所以我需要为每个触摸事件触发搜索。

我尝试使用线程在后台执行搜索,代码如下:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
                 [NSThread detachNewThreadSelector:@selector(filter:)  toTarget:self  withObject:searchString];
           return NO;
        }

// Filter function looks like this
-(void) filter:(NSString *)search {
         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
         [self.filteredList removeAllObjects]; // empty array of results
         for (NSString *s in self.keys ) {
              NSComparisonResult result = [s compare:search options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [search length])];
              if (result == NSOrderedSame) {
                   [self. filteredList addObject:s ];
              }
         }
         [ self.searchDisplayController.searchResultsTableView reloadData];
         [pool release];
    }

但我的应用程序随机崩溃,并显示以下消息:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (1) beyond bounds (0). 

我确定这是因为我没有正确使用线程。

我也尝试使用[self performSelector:@selector(filter:) withObject:searchString afterDelay:0.5];,但我也面临应用程序崩溃。

处理此问题的最佳方法是什么?我对线程并不是很好,但我认为这是最好的方法,不是吗?我也尝试过使用SQLite的解决方案,但应用程序仍然没有那么敏感。

我的数据实际上是邮政编码和城市(36000个独特的不同城市,但6500个唯一邮政编码,因为多个城市可以使用相同的邮政编码)。我希望我的搜索项目是邮政编码或城市名称。我知道一本大字典肯定不是最好的结构。我如何组织我的数据以提高效率?

感谢您帮助我。

1 个答案:

答案 0 :(得分:2)

问题是您的搜索字符串比数组中的原始字符串长。当从0到[搜索长度]进行比较时,你正在超出s。您应该首先确保s比搜索长:

for (NSString *s in self.keys ) {
    if ([s length]>=[search length]) {
          NSComparisonResult result = [s compare:search options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [search length])];
          if (result == NSOrderedSame) {
               [self. filteredList addObject:s ];
          }
     }
}