我的iOS应用程序的一个视图是UISearchDisplay。我将其设计为提前输入搜索,这样无论何时用户输入新字符,都会重新填充表格。我通过实现UISearchDisplayDelegate协议方法完成了这个:
searchDisplayController:shouldReloadTableForSearchString:
在这个方法中,我获取提供的字符串并将其附加到我的查询URL。然后我创建一个新的NSURLConnection并提交一个新的异步请求。我通过委托方法接收和追加数据:
connection:didReceiveData:
连接完成下载数据后,通过以下方法:
connectionDidFinishLoading
我将数据传递给NSXMLParser的一个实例。接收的数据是我的数据库中与给定字符串匹配的所有联系人的XML文件。数据完成解析后,我重新加载表。
我的问题:如果用户输入足够快的文本,则会同时进行多个连接和解析任务。这是一个问题,因为我有一个NSMutableData实例,我将数据附加到并解析。希望你能看到我的目标。
有没有人有任何改进我的实施和/或解决这个关键部分问题的建议?
答案 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];
}