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

时间:2014-07-18 21:08:46

标签: ios core-data

我继续读到在使用核心数据时我应该使用[_context performBlock]:^...进行异步搜索。我无法想象我的生活是如何订阅结束或完整的事件谈论这个块。换句话说,在我的代码中,我在获取数据之前使用UIActivityIndicatorView,并且我想在检索数据后删除此视图。但是,我不明白如何正确地实现这一目标。 在过去,我使用了dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{...然后实现了

dispatch_async(dispatch_get_main_queue(), ^(void) { 

知道que何时完成后台处理。 我可能完全错了,但我想问我这个问题。我需要实现什么代理或者我需要订阅什么方法。要知道我的提取完成时间,我刚刚在performBlock:

内执行了

我的最终目标是在获取之前设置UIActivityIndi​​catorView,获取数据并将其设置为不可见。提前感谢你们提供的任何帮助。

**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];

                });
            });
        }];
    }
}

1 个答案:

答案 0 :(得分:1)

在我开始撰写回复后,您似乎已经明显改变了您的问题......

请告诉我这是否有用 - 否则我会删除,因为它不再与您的问题有关。


一般来说,在我看来,第二次NSFetchedResultsController是过度的。

请注意,这是基于您已经以编程方式或使用故事板正确实现UISearchBarUISearchDisplayController的实例。如果您不确定,请阅读我写的previous answer可能会有所帮助。

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

最后我的回答,我更愿意实现以下代码,为实现UITableViewController的任何NSFetchedResultsController创建可靠的搜索方法...

创建公共或私有财产(取决于您的要求)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委托方法。

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self setSearchResults:nil];
}

希望这有帮助。