正确地使用执行块异步抓取



我继续阅读,我应该使用[_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,在我看来和经验,是多余的。

请注意,这是在理解您已经正确地实现了UISearchBarUISearchDisplayController的实例的基础上编写的,无论是通过编程还是使用故事板。如果你不确定,请阅读我之前写的答案,可能会有所帮助。

由于您在问题中使用了UISearchDisplayController委托方法,我将假设您已经声明了针对@interface(即<UISearchBarDelegate, UISearchDisplayDelegate>)的预期用途。

所以最后要我的答案,我更喜欢实现以下代码来为任何实现NSFetchedResultsControllerUITableViewController创建一个可靠的搜索方法…

创建一个公共或私有属性(取决于您的要求)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];
}

最新更新