Как использовать NSFetchedResultsController и UISearchDisplayController - PullRequest
14 голосов
/ 03 февраля 2010

Я создавал приложение для iPhone с использованием Core Data.

Прежде всего, имеет ли смысл использовать NSFetchedResultsController и UISearchDisplayController вместе для получения результата? Вы бы порекомендовали что-нибудь еще?

Я довольно долго пытался объединить NSFetchedResultController и UISearchDisplayController. Я думал об установке NSPredicate в методе (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption для NSFetchedResultController из UIViewController. Но это не очень хорошо работает.

Итак, у вас есть идея, как реализовать решение для моей проблемы? Спасибо, что уже опубликовали ответы или ссылки на хорошие учебники.

EDIT

Вот мой код. Методы 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;
} 

Ответы [ 3 ]

21 голосов
/ 04 марта 2010

Взглянув на ваш код, он тут же. Я столкнулся с проблемами, используя этот метод для изменения поиска. Исправление: очистите кеш!

Допустим, вы инициировали свой полученный контроллер результатов следующим образом. Обратите внимание на свойство cacheName.

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest] managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"UserSearch"];

При изменении предиката просто добавьте:

 [NSFetchedResultsController deleteCacheWithName:@"UserSearch"];

Как магия, она будет хорошо работать.

Вы также захотите отслеживать, когда контроллер отображения поиска завершит поиск, и стереть свой предикат.

Хотя эта тема выглядит мертвой, я нашел ее в Google, так что, возможно, кто-то там воспользуется этим. :)

7 голосов
/ 14 июля 2010

Согласно документации, вы либо захотите отфильтровать результаты в массив, используя предикат, либо повторно инициализировать fetchedResultsController.

Важно: Вы не должны изменять запросить запрос после того, как инициализировал контроллер. За Например, вы не должны изменять предикат или порядок сортировки.

- NSFetchedResultsController

(Я бы прокомментировал ответ простоя, но я без кармы.)

1 голос
/ 03 февраля 2010

Похоже, вы просто заинтересованы в получении и отображении объектов. В этом случае вы НЕ используете контроллер отображения поиска. Контроллер отображения поиска используется с панелью поиска, которая позволяет вводить текстовый поиск вашего контента, введенный пользователем.

Обычно вы используете выбранный контроллер результатов, чтобы помочь в реализации методов источника данных табличного представления и методов делегирования. Кроме того, вы создаете и используете запрос на выборку для вашего контроллера полученных результатов. Это все пример (см. Код шаблона, предоставленный Apple при создании нового проекта с выбранной опцией «Использовать базовые данные для хранения»).

Именно в запросе на выборку вы можете создать и указать предикат. Это позволит вам фильтровать объекты, отображаемые в вашей таблице. Например:

// only fetch objects with myAttribute set to someValue
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myAttribute == %@",someValue];
[fetchRequest setPredicate:pred];
...