#objective_c #ios #coredata
В наличии UITableView, контент которой заполняется из Core Data при помощи fetchedResultsController'а:
- (NSFetchedResultsController *) fetchedResultsController
{
NSLog(@"fetchedResultsController");
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Client"
inManagedObjectContext:[[PTDataManager
sharedManager] managedObjectContext]];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"agency_server_id
== %@", agency.server_id];
fetchRequest.predicate = predicate;
NSSortDescriptor *sortByName1Descriptor = [[NSSortDescriptor alloc] initWithKey:@"lastname"
ascending:YES];
NSSortDescriptor *sortByName2Descriptor = [[NSSortDescriptor alloc] initWithKey:@"firstname"
ascending:YES];
NSSortDescriptor *sortByName3Descriptor = [[NSSortDescriptor alloc] initWithKey:@"middlename"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: sortByName1Descriptor,
sortByName2Descriptor, sortByName3Descriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
managedObjectContext:[[PTDataManager sharedManager] managedObjectContext] sectionNameKeyPath:nil
cacheName:nil];
fetchedResultsController.delegate = self;
return fetchedResultsController;
}
другие делегатские методы не реализованы так как таблица заполняется один раз, при
входе во viewController и больше не меняется. Стоит задача реализовать поиск по контенту
таблицы с отображением в таблице только результатов соответствующих значениям введенным
в searchBar. Реализовываю метод:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self reloadTableView];
}
и соответственно триггеруемый метод для отображения в таблице:
- (void)reloadTableView
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Client"
inManagedObjectContext:[[PTDataManager
sharedManager] managedObjectContext]];
[fetchRequest setEntity:entity];
NSPredicate *filterPredicate;
NSString *searchString = self.searchBar.text;
NSMutableArray *predicateArray = [[NSMutableArray alloc] init];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"agency_server_id
CONTAINS[cd] %@", agency.server_id]];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"firstname CONTAINS[cd]
%@", searchString]];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"lastname CONTAINS[cd]
%@", searchString]];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"middlename CONTAINS[cd]
%@", searchString]];
filterPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray];
[fetchRequest setPredicate:filterPredicate];
NSSortDescriptor *sortByName1Descriptor = [[NSSortDescriptor alloc] initWithKey:@"lastname"
ascending:YES];
NSSortDescriptor *sortByName2Descriptor = [[NSSortDescriptor alloc] initWithKey:@"firstname"
ascending:YES];
NSSortDescriptor *sortByName3Descriptor = [[NSSortDescriptor alloc] initWithKey:@"middlename"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: sortByName1Descriptor,
sortByName2Descriptor, sortByName3Descriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
managedObjectContext:[[PTDataManager sharedManager] managedObjectContext] sectionNameKeyPath:nil
cacheName:nil];
fetchedResultsController.delegate = self;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(@"Unresolved error %@, %@", [error localizedDescription], [error localizedFailureReason]);
abort();
};
[self.clientsTableView reloadData];
}
который похож на fetchedResultsController но как видно имеется отличия в ограничении
выборки. Проблема в том, что в таком виде вызов -reloadTableView дергает и сам fetchedResultsController,
в результате фетч меняется в процессе ввода символов в searchBar. В таблице появляется
все что вытянул fetchedResultsController и плюс все остальное что совпадает с содержимым
searchBarа. Визуально: при вводе символов в поле поиска таблица не сокращает количество
результатов а увеличивает.
Вопрос:
на каком этапе реализации поиска по уже фетченой выборке я делаю ошибку? Могу ли
я как-то изменить вторичный фетч для поиска по уже полученным из первичного фетча результатам?
Ответы
Ответ 1
Вопрос решился через составной предикат с использованием +orPredicateWithSubpredicates: и +andPredicateWithSubpredicates:: NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:firstPredicate, secondPredicate, nil]]; NSPredicate *andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:thirdPredicate, fourthPredicate, nil]]; NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:orPredicate, andPredicate, nil]]; [fetchRequest setPredicate:finalPredicate]; В таком виде через AND сохраняется результат предварительного фетча и через дополнительные OR происходит его фильтрация согласно критериям поискаОтвет 2
Посмотрите первый ответ, похоже ваша ситуация: How to filter NSFetchedResultsController (CoreData) with UISearchDisplayController/UISearchBar
Комментариев нет:
Отправить комментарий