У меня возникли некоторые проблемы со смешанным, индексированным поисковым набором результатов из контроллера NSFetchedResults.Я настроил его для хранения индексированного первого инициала AZ для сущности, а затем хочу, чтобы он отображал числовые первые инициалы (т. Е. #, Как будет делать UILocalizedIndexCollation).
Я уже написал код, который сохраняет атрибут firstInitial объекта Artist как NSString @ "#", если полное имя начинается с цифры, и мне кажется, что код наполовину работает в моемUITableViewController с настроенным дескриптором сортировки.Проблема в том, что он работает только до тех пор, пока я не закрою / не перезапущу приложение.
На этом этапе раздел # из полученных результатов отображается вверху.Он будет оставаться там до тех пор, пока я не принудительно заставлю изменение данных (добавить / удалить управляемый объект), а затем произведу поиск записи и очисту поиск (используя searchDisplayController).В этот момент вступит в силу переупорядочение раздела, а раздел # будет перемещен вниз ...
Я явно что-то упускаю / слишком долго смотрел на один и тот же код.Кроме того, есть гораздо более простой способ сделать это, которого я не знаю / не могу найти в Google!
Любая помощь будет принята!
Спасибо
Sean
Ниже приведен соответствующий код из моего UITableViewController.
- (void)viewDidLoad
{
// ----------------------------------
// Various other view set up things in here....
// ...
// ...
// ----------------------------------
NSError *error;
if (![[self artistResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Failed to fetch artists: %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)artistResultsController {
if (_artistResultsController != nil) {
return _artistResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Artist" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];
NSSortDescriptor *initialSort = [[NSSortDescriptor alloc]
initWithKey:@"firstInitial"
ascending:YES
comparator:^(id obj1, id obj2) {
// Various number conditions for comparison - if it's a # initial, then it's a number
if (![obj1 isEqualToString:@"#"] && [obj2 isEqualToString:@"#"]) return NSOrderedAscending;
else if ([obj1 isEqualToString:@"#"] && ![obj2 isEqualToString:@"#"]) return NSOrderedDescending;
if ([obj1 isEqualToString:@"#"] && [obj2 isEqualToString:@"#"]) return NSOrderedSame;
// Else it's a string - compare it by localized region
return [obj1 localizedCaseInsensitiveCompare:obj2];
}];
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:initialSort, nameSort, nil]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:_context
sectionNameKeyPath:@"firstInitial"
cacheName:nil];
self.artistResultsController = theFetchedResultsController;
_artistResultsController.delegate = self;
[nameSort release];
[initialSort release];
[fetchRequest release];
[_artistResultsController release];
return _artistResultsController;}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return nil;
} else {
return [[[_artistResultsController sections] objectAtIndex:section] name];
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return nil;
} else {
return [[NSArray arrayWithObject:UITableViewIndexSearch] arrayByAddingObjectsFromArray:
[[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]];
}
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return 0;
} else {
if (title == UITableViewIndexSearch) {
[tableView scrollRectToVisible:self.searchDisplayController.searchBar.frame animated:NO];
return -1;
}
else {
for (int i = [[_artistResultsController sections] count] -1; i >=0; i--) {
NSComparisonResult cr =
[title localizedCaseInsensitiveCompare:
[[[_artistResultsController sections] objectAtIndex:i] indexTitle]];
if (cr == NSOrderedSame || cr == NSOrderedDescending) {
return i;
}
}
return 0;
}
}
}
РЕДАКТИРОВАТЬ: забыл упомянуть - мой поисковый фильтр использует предикат на контроллере fetchedResults, поэтому это вызывает новый запрос на выборкувот так
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
NSFetchRequest *aRequest = [_artistResultsController fetchRequest];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", searchText];
// set predicate to the request
[aRequest setPredicate:predicate];
// save changes
NSError *error = nil;
if (![_artistResultsController performFetch:&error]) {
NSLog(@"Failed to filter artists: %@, %@", error, [error userInfo]);
abort();
}
}