GCDを実装すると、UISearchDisplayControllerにCoreDataの結果を表示できません。これがないと機能しますが、明らかにUIがブロックされます。
SearchTableViewControllerには、次の2つのメソッドがあります。
- (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]];
}
私の問題は、[coreDataMasterfetchResultsFromCoreDataEntity]から配列を返すことにあると推測できます。以下はその方法です。
- (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];
}
したがって、スレッドは、結果をself.filteredLocationsArrayに返すまでに実行を終了していません。NSDictionaryをこのメソッドに渡すNSNotificationを追加してみました。
- (void)updateSearchResults:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSArray *array = [userInfo objectForKey:@"results"];
self.filteredLocationsArray = [NSMutableArray arrayWithArray:array];
[self.tableView reloadData];
}
また、searchViewControllerを次のように更新してみました
[self.searchDisplayController.searchResultsTableView reloadData];
しかし、役に立たない。誰かが私を正しい方向に向けて、私がどこで間違っているのかを教えてくれたら、本当にありがたいです。
ありがとう
編集
将来の参考のために、クリストファーのソリューションの何かを明確にしたいと思います。
このメソッドを呼び出すときは、GCD呼び出しを競合ブロックのメインキューに配置します。また、tableViewをリロードするための変更にも注意してください。
例
[coreDataMaster fetchResultsFromCoreDataEntity:(NSString *)entity usingPredicate:(NSPredicate *)predicate completionHandler:^(NSArray *cities){
dispatch_async(dispatch_get_main_queue(), ^{
self.filteredLocationsArray = cities;
[self.searchDisplayController.searchResultsTableView reloadData];
});
}];