2

我的 iOS 应用程序的一个视图是 UISearchDisplay。我将其设计为预先输入的搜索,这样每当用户输入一个新字符时,表格就会重新填充。我通过实现 UISearchDisplayDelegate 协议方法做到了这一点:

searchDisplayController:shouldReloadTableForSearchString:

在这种方法中,我将提供的字符串附加到我的查询 URL 中。然后我创建一个新的 NSURLConnection 并提交一个新的异步请求。我通过委托方法接收和附加数据:

connection:didReceiveData:

连接完成下载数据后,通过以下方法:

connectionDidFinishLoading

我将数据传递给 NSXMLParser 的一个实例。接收到的数据是我的数据库中与给定字符串匹配的所有联系人的 XML 文件。数据解析完成后,我重新加载表。

我的问题:如果用户输入文本的速度足够快,就会有多个连接和解析任务同时进行。这是一个问题,因为我有一个 NSMutableData 实例,我将数据附加到并解析。希望你能看到我的目标。

有没有人对改进我的实施和/或解决这个关键部分问题有任何建议?

4

2 回答 2

0

NSXMLParser不是异步的。这让很多人感到困惑,因为他们认为这是由于它使用了委托回调方法。但是,实际上该parse方法在所有解析完成之前不会返回。

因此,虽然您可能同时有多个连接,但除非您自己对其进行多线程处理,否则不会发生多个解析操作。

要解决多连接问题,不如每个连接只有一个 NSMutableData,而不是一个?有很多方法可以做到这一点:您可能想查看以下问题的答案以获得想法。

于 2012-07-13T11:40:35.463 回答
-1

在Cancelable asynchronous search with UISearchDisplayController中描述了一个很好的实现

解决方案的要点是这样的:

  • 创建一个NSOperationQueue实例,您将在其中执行搜索操作并将其保存到UISearchDisplayDelegate实现的属性中,我们将其命名为searchQueue

  • 实现searchDisplayController:shouldReloadTableForSearchString:方法。请注意,此方法返回一个BOOL值,该值指示UISearchDisplayController实例重新加载表视图。该方法可以像这样实现:

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller 
    shouldReloadTableForSearchString:(NSString *)searchString {
        if ([searchString isEqualToString:@""] == NO) {
            [self.searchQueue cancelAllOperations];
            [self.searchQueue addOperationWithBlock:^{
    
              NSArray *results = // fetch the results from
              // somewhere (that can take a while to do)
    
              // Ensure you're assigning to a local variable here.
              // Do not assign to a member variable.  You will get
              // occasional thread race condition related crashes 
              // if you do.            
    
              [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                // Modify your instance variables here on the main
                // UI thread.
                [self.searchResults removeAllObjects]; 
                [self.searchResults addObjectsFromArray:results];
    
                // Reload your search results table data.
                [controller.searchResultsTableView reloadData];
              }];
            }];
    
            return NO;
    
        } else {
            [self.searchResults removeAllObjects];
            return YES;
        }
    }
    
  • 当用户关闭搜索 UI 时,不要忘记取消任何挂起的操作。

         - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
             [self.searchQueue cancelAllOperations];
         }
    
于 2014-06-29T14:50:04.757 回答