Как использовать NSFetchedResultsController и UISearchDisplayController
Я создаю приложение iPhone с использованием основных данных.
Во-первых, имеет ли смысл использовать NSFetchedResultsController и UISearchDisplayController вместе для получения результата? Вы порекомендовали бы что-нибудь еще?
Я пытался довольно долго комбинировать NSFetchedResultController и UISearchDisplayController. Я думал о настройке NSPredicate в методе (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
для NSFetchedResultController UIViewController. Но это плохо работает.
Итак, вы знаете, как реализовать решение для моей проблемы? Благодарим вас за отправку ответов или ссылок на хорошие уроки.
ИЗМЕНИТЬ
Вот мой код. Методы UISearchDisplayDelegate вызывают метод (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
, который должен установить предикат в NSFetchedResultController. Я также добавил код NSFetchedResultController.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSString *query = self.searchDisplayController.searchBar.text;
if (query && query.length) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Name contains[cd] %@", query];
[fetchedResultsController.fetchRequest setPredicate:predicate];
}
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// Handle error
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Ответы
Ответ 1
Взгляд на ваш код, его прямо там. Я столкнулся с проблемами, используя этот метод для изменения поиска. Исправление: очистите кеш!
Предположим, что вы инициировали свой контроллер результатов, как показано ниже. Обратите внимание на свойство cacheName.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest] managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"UserSearch"];
По мере изменения вашего предиката просто добавьте:
[NSFetchedResultsController deleteCacheWithName:@"UserSearch"];
Как магия, она будет работать красиво.
Вы также захотите отслеживать, когда контроллер отображения поиска завершит поиск, и вытрите предикат.
Хотя этот поток выглядит мертвым, я нашел его в google, поэтому, возможно, кто-то там будет использовать это.:)
Ответ 2
В соответствии с документами вы либо хотите отфильтровать результаты в массиве, используя предикат, либо повторно инициализируйте fetchedResultsController.
Важно: вы не должны изменять запрос на выбор после того, как вы инициализировал контроллер. Для Например, вы не должны изменять предикат или порядок сортировки.
- NSFetchedResultsController
(Я бы прокомментировал простоя, но я без кармы.)
Ответ 3
Похоже, вы просто заинтересованы в получении и отображении объектов. В этом случае вы НЕ используете контроллер отображения поиска. Контроллер дисплея поиска используется с панелью поиска, чтобы помочь с предоставлением пользовательских текстовых запросов вашего контента.
Обычно вы используете выбранный контроллер результатов, чтобы помочь в реализации методов представления данных таблиц и делегирования. Кроме того, вы создаете и используете запрос на выборку для выбранного получателя результатов. Это все котельная плита (см. Код шаблона, предоставленный Apple при создании нового проекта с выбранной опцией "Использовать основные данные для хранения" ).
В запросе выборки вы можете создать и указать предикат. Это позволит вам фильтровать объекты, отображаемые вашей таблицей. Например:
// only fetch objects with myAttribute set to someValue
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myAttribute == %@",someValue];
[fetchRequest setPredicate:pred];