Updating UISearchDisplayController with Core Data results using GCD

Posted by Brian Halpin on Stack Overflow See other posts from Stack Overflow or by Brian Halpin
Published on 2012-11-26T23:01:36Z Indexed on 2012/11/26 23:03 UTC
Read the original article Hit count: 234

I'm having trouble displaying the results from Core Data in my UISearchDisplayController when I implement GCD. Without it, it works, but obviously blocks the UI.

In my SearchTableViewController I have the following two methods:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    // Tell the table data source to reload when text changes
    [self filterContentForSearchText:searchString];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

// Update the filtered array based on the search text
-(void)filterContentForSearchText:(NSString*)searchText
{
    // Remove all objects from the filtered search array
    [self.filteredLocationsArray removeAllObjects];

    NSPredicate *predicate = [CoreDataMaster predicateForLocationUsingSearchText:@"Limerick"];

    CoreDataMaster *coreDataMaster = [[CoreDataMaster alloc] init];

    // Filter the array using NSPredicate
    self.filteredLocationsArray = [NSMutableArray arrayWithArray:
                                   [coreDataMaster fetchResultsFromCoreDataEntity:@"City" UsingPredicate:predicate]];

}

You can probably guess that my problem is with returning the array from [coreDataMaster fetchResultsFromCoreDataEntity]. Below is the method:

- (NSArray *)fetchResultsFromCoreDataEntity:(NSString *)entity UsingPredicate:(NSPredicate *)predicate
{    
    NSMutableArray *fetchedResults = [[NSMutableArray alloc] init];

    dispatch_queue_t coreDataQueue = dispatch_queue_create("com.coredata.queue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(coreDataQueue, ^{


        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entityDescription = [NSEntityDescription
                                                  entityForName:entity inManagedObjectContext:self.managedObjectContext];

        NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
        NSArray *sortDescriptors = [NSArray arrayWithObjects:nameSort, nil];

        [fetchRequest setEntity:entityDescription];
        [fetchRequest setSortDescriptors:sortDescriptors];

        // Check if predicate is set
        if (predicate)
        {
            [fetchRequest setPredicate:predicate];
        }

        NSError *error = nil;

        NSArray *fetchedManagedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

        for (City *city in fetchedManagedObjects)
        {
            [fetchedResults addObject:city];
        }

        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSArray arrayWithArray:fetchedResults] forKey:@"results"];

        [[NSNotificationCenter defaultCenter]
         postNotificationName:@"fetchResultsComplete"
         object:nil userInfo:userInfo];

    });

    return [NSArray arrayWithArray:fetchedResults];
}

So the thread hasn't finished executing by the time it returns the results to self.filteredLocationsArray. I've tried added a NSNotification which passes the NSDictionary to this method:

- (void)updateSearchResults:(NSNotification *)notification
{
    NSDictionary *userInfo = notification.userInfo;
    NSArray *array = [userInfo objectForKey:@"results"];

    self.filteredLocationsArray = [NSMutableArray arrayWithArray:array];

    [self.tableView reloadData];
}

I've also tried refreshing the searchViewController like

[self.searchDisplayController.searchResultsTableView reloadData];

but to no avail. I'd really appreciate it if someone could point me in the right direction and show me where I might be going wrong.

Thanks

© Stack Overflow or respective owner

Related posts about core-data

Related posts about grand-central-dispatch