Ios 使用执行块正确异步获取
我继续读到,在使用核心数据时,我应该使用Ios 使用执行块正确异步获取,ios,core-data,Ios,Core Data,我继续读到,在使用核心数据时,我应该使用[\u context performBlock]:^…进行异步搜索。我一辈子都想不出的是如何订阅这个街区的结尾或完整事件。换句话说,在我的代码中,我在获取数据之前使用了UIActivityIndicatorView,并且我希望在检索数据后删除此视图。然而,我不明白如何正确地完成这一点。 在过去,我使用了dispatch\u async(dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\
[\u context performBlock]:^…
进行异步搜索。我一辈子都想不出的是如何订阅这个街区的结尾或完整事件。换句话说,在我的代码中,我在获取数据之前使用了UIActivityIndicatorView
,并且我希望在检索数据后删除此视图。然而,我不明白如何正确地完成这一点。
在过去,我使用了dispatch\u async(dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u DEFAULT,0),^{…
,然后实现
dispatch_async(dispatch_get_main_queue(), ^(void) {
了解que何时完成后台处理。
我可能完全错了,但我提出了一个问题。我需要实现什么委托,或者我需要订阅什么方法。要知道我的获取何时完成,我刚刚在performBlock:
同样,我的最终目标是在获取之前设置UIActivityIndicatorView可见,获取数据并将其设置回不可见。提前感谢你们提供的任何帮助
**update**
由于需要搜索大量记录,我需要异步进行搜索。我有大约195k条记录,因此当用户开始在搜索栏中键入字母时,如果我尝试在主线程中执行此操作,会有1到2秒的延迟。因此,我会抛出一个UIActivityIndicatorView
a然后我在后台线程上进行搜索,完成后更新主线程
这是我用来完成这个的代码
@property (strong, nonatomic) NSArray *filteredLocations;
@property (strong, nonatomic) NSArray * locationsFiltered;
//returns the search for this particular search.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
if ([searchString length ]>= 3) {
[self searchForText:searchString];
return YES;
}
else{
self.filteredLocations = nil;
return NO;
}
//return YES;
}
- (void)searchForText:(NSString *)searchText
{
if (self.context && self.isSearching == FALSE)
{
//[searchController ]
//[self.searchDisplayController.searchResultsTableView.]
self.isSearching = TRUE;
NSString *predicateFormat = @"%K BEGINSWITH[cd] %@ and state ==%@";
NSString *searchAttribute = @"name";
self.filteredLocations = nil;
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute, searchText,Searchstate];
[self.searchFetchRequest setPredicate:predicate];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
if (self.spinnerShowing ==FALSE) {
spinner.center = CGPointMake(160, 190);
spinner.hidesWhenStopped = YES;
spinner.color = [UIColor grayColor];
[self.view addSubview:spinner];
//self.spinnerShowing = ;
[spinner startAnimating];
}
[_context performBlock:^(void){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
self.filteredLocations = [self.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&error];
NSLog(@"this is how many items are in the filtered locations at this time %i", [_filteredLocations count]);
if (error)
{
NSLog(@"searchFetchRequest failed: %@",[error localizedDescription]);
}
dispatch_async(dispatch_get_main_queue(), ^(void) {
NSLog(@"stopping the spinner now.");
self.spinnerShowing = FALSE;
[spinner stopAnimating];
[spinner hidesWhenStopped];
self.isSearching = FALSE;
//self.searchDisplayController.searchResultsTableView.hidden = NO;
// [searchController reloadData];
[self.searchDisplayController.searchResultsTableView reloadData];
});
});
}];
}
}
在我开始写我的回复后,你的问题似乎有了很大的改变 让我知道这是否有用-否则我将删除,因为它不再涉及您的问题
通常,根据我的观点和经验,第二个
nsfetchedresultscoontroller
是过分的
请注意,编写本文的前提是,您已经通过编程或使用故事板正确实现了UISearchBar
和UISearchDisplayController
的实例。如果您不确定,请阅读我写的一篇文章
当您在问题中使用UISearchDisplayController
委托方法时,我假设您已针对@界面
(即
)声明了您的预期用途
最后,对于我的答案,我更愿意实现以下代码,为实现NSFetchedResultsController
的任何UITableViewController
创建可靠的搜索方法
创建公共或私有属性(取决于您的要求)NSMutableArray
以保存搜索结果的内容:
@property (nonatomic, retain) NSMutableArray *searchResults;
在以下情况下,可以使用此NSMutableArray
设置UITableViewController
数据源方法:
if (tableView == self.searchDisplayController.searchResultsTableView) {
//code for searchResultsTableView
}
然后我使用
UISearchDisplayController
委托方法来控制self.searchController.searchResultsTableView
的任何活动实例
这是最重要的一个
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
// Set search predicate and filter array
if (searchString && searchString.length) {
// Your predicateFormat and searchAttribute
NSString *predicateFormat = @"%K BEGINSWITH[cd] %@ and state ==%@";
NSString *searchAttribute = @"name";
// My code
NSPredicate *searchPredicate = nil;
NSArray *fetchedObjects = nil;
NSMutableArray *arrayResults = nil;
[self.searchResults removeAllObjects];
searchPredicate = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute, searchString, searchState];
fetchedObjects = self.fetchedResultsController.fetchedObjects;
arrayResults = [NSMutableArray arrayWithArray:[fetchedObjects filteredArrayUsingPredicate:searchPredicate]];
[self setSearchResults:arrayResults];
}
// Return YES to reload the search result table view
return YES;
}
PS-将Searchstate变量更改为Searchstate
您可能还希望实现以下UISearchDisplayController
delegate方法
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self setSearchResults:nil];
}
希望这能有所帮助。Andrew感谢您的回复。我将尝试一下您的解决方案。您是对的,我戏剧性地更改了我的问题。已经6个小时了,我对我的问题感到更加沮丧。然而,我最大的问题是我需要异步执行此操作。原因是我不想锁定我的主线程。你对如何正确完成这项任务有什么建议吗?非常感谢。@Miguel一些问题…1.为什么要求你进行异步搜索?2.你的搜索是否超出了
NSFetchedResultsController
?3.请编辑你的问题以提供更多信息定义您试图实现的目标-例如,NSFetchedResultsController
feedsUITableViewController
数据源方法,并且您只需要从外部数据源获取FRC/下载记录的当前fetchedObject
属性中的不相关/相关记录/记录Source???问题已更新我不需要获取不相关的记录,但有太多记录,ui往往会冻结1或2秒,因此我尝试从后台线程执行此操作的原因。我担心的是我可能没有正确执行此操作。@Miguel您是否考虑过或调查过对NSFetchedResultsC的错误处理ontroller
results而不是尝试后台获取?另一本书建议@Miguel…这是一本老书,但值得一读——迈克尔·普列瓦特和罗伯特·沃纳(即将被他们的新书《使用核心数据的Pro-iOS持久化》取代)的第7章,题为“优化性能和内存使用情况”。我建议您完成第7章中的教程。它将教您很多关于错误处理以及如何高效调用核心数据堆栈的知识。虽然我更喜欢Zarra风格的核心数据代码,但这本相对古老的Privat/Warner书采用了一种实用的方法来教育读者,我发现这对读者非常有帮助。