14

Я создаю приложение iPhone с использованием Core Data.Как использовать NSFetchedResultsController и UISearchDisplayController

Прежде всего, имеет смысл использовать 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; 
} 

ответ

21

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

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

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

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

[NSFetchedResultsController deleteCacheWithName:@"UserSearch"]; 

Как по волшебству, он будет работать хорошо.

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

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

+1

Это решение работает, но является довольно дорогостоящим, заставляя контроллер получаемых результатов выполнять многочисленные поездки в постоянный магазин. Кроме того, если вы не собираетесь использовать кеш, зачем его указывать? Просто пройди ноль. Тем не менее, гораздо лучшее решение - это то, на что @psuedonick намекает: оставьте fetchedResultsController делать то, что он делает лучше всего, а именно управлял полученными результатами и использовал filterArrayUsingPredicate: on fetchedObjects, чтобы заполнить filterListContent. –

+2

Чтобы уточнить, если вы используете решение, которое я описываю, вы должны * указать кеш: для этого нужно, чтобы получаемый им контроллер получал необходимые для хранения fetchedObjects, чтобы их можно было эффективно искать с помощью filterArrayUsingPredicate: –

+0

Спасибо Elise, я думаю, ваш путь путь. Я завершу шаги по реализации контроллера отображения отображения в контроллере табличного представления в другом сообщении позже. Мне нужно столько времени, чтобы найти наилучшую практику по этому вопросу. – Philip007

1

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

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

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

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

Ну, я не упомянул ясно, что я на самом деле реализации немного поиск. Я уже пытался установить предикат в NSFetchedResultsController для фильтрации результатов, точно так же, как ваш размещенный код, но ничего не происходит, объекты не найдены. Любая идея, почему предикат не работает? Это просто сравнение между строкой поиска и именем объекта. Спасибо за помощь – burki

+0

Вы должны добавить сведения о предикате или задать новый вопрос об этом. Кроме того, всегда полезно показывать код, который вы используете, задавая вопросы. – gerry3

7

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

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

- NSFetchedResultsController

(. Я бы прокомментировать ответ на холостом ходу, но я карма меньше)

Смежные вопросы