在iOS中使用异步网络调用创建预先输入UISearchDisplay

时间:2012-07-13 11:29:36

标签: ios asynchronous nsurlconnection uisearchdisplaycontroller type-ahead

我的iOS应用程序的一个视图是UISearchDisplay。我将其设计为提前输入搜索,这样无论何时用户输入新字符,都会重新填充表格。我通过实现UISearchDisplayDelegate协议方法完成了这个:

searchDisplayController:shouldReloadTableForSearchString:

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

connection:didReceiveData:

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

connectionDidFinishLoading

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

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

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

2 个答案:

答案 0 :(得分:0)

NSXMLParser不是异步的。这个人绊倒了很多人,因为他们认为这是由于它使用了委托回调方法。但是,实际上parse方法在完成所有解析之后才会返回。

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

要解决多连接问题,如何使用单个NSMutableData而不是每个连接一个?有很多方法可以做到这一点:您可能希望查看以下问题的答案。

答案 1 :(得分:-1)

Cancellable asynchronous searching 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;
        }
    }
    
  • 当用户取消搜索界面时,不要忘记取消任何待处理的操作。

         - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
             [self.searchQueue cancelAllOperations];
         }