我继续阅读,我应该使用[_context performBlock]:^...
做异步搜索时使用核心数据。我一辈子都弄不明白的是如何订阅结束或完整的事件,就像这个块一样。换句话说,在我的代码中,我在获取数据之前使用UIActivityIndicatorView
,一旦数据被检索,我想删除此视图。然而,我不明白如何正确地完成这一点。过去我使用dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{...
,然后实现
dispatch_async(dispatch_get_main_queue(), ^(void) {
表示队列何时完成后台处理。我可能完全搞错了,但我想我应该问这个问题。我需要实现什么委托或者我需要订阅什么方法。要知道我的取取完成时,我刚刚在performBlock:
再次,我的最终目标是设置一个UIActivityIndicatorView可见之前取回,取回数据并设置它不可见。提前感谢你们提供的任何帮助。
**update**
我需要做搜索异步由于大量的记录,我必须通过搜索。我大约有195k条记录,所以如果我在主线程中尝试这样做,当用户开始在搜索栏中键入字母时,可能会有1到2秒的延迟。因此,我抛出一个UIActivityIndicatorView
的原因,然后我在后台线程上进行搜索,并在我完成时更新主线程。
这是我用来完成这个的代码。
@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];
});
});
}];
}
}
在我开始写回复后,你的问题似乎有了很大的改变…
让我知道这是否有用,否则我将删除,因为它不再与你的问题相关。
一般来说,第二个NSFetchedResultsController
,在我看来和经验,是多余的。
请注意,这是在理解您已经正确地实现了UISearchBar
和UISearchDisplayController
的实例的基础上编写的,无论是通过编程还是使用故事板。如果你不确定,请阅读我之前写的答案,可能会有所帮助。
由于您在问题中使用了UISearchDisplayController
委托方法,我将假设您已经声明了针对@interface
(即<UISearchBarDelegate, UISearchDisplayDelegate>
)的预期用途。
所以最后要我的答案,我更喜欢实现以下代码来为任何实现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 !
您可能还想实现以下UISearchDisplayController
委托方法。
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self setSearchResults:nil];
}