Изменение сортировки в NSFetchedResultsController на лету
Я пытаюсь изменить сортировку в NSFetchController "на лету", каким-то сегментированным элементом управления. Для сортировки типа A- > Z Z- > A.
Что мне нужно сделать, чтобы сделать это? Я следую примеру Джеффа Ламархе: Здесь
Мне нужно создать новый NSFetchedResultsController, а затем установить его или просто создать новый NSFetchRequest и сделать
fetchedResultController.fetchRequest = newFetchRequest
а затем моя таблица будет автоматически обновляться?
Ответы
Ответ 1
Я столкнулся с той же проблемой, и я смог исправить ее, просто установив дескрипторы сортировки в FetchRequestController FetchRequest, а затем выполнив fetch (performFetch) и, наконец, перезагрузив данные в виде таблицы.
NSArray *sortDescriptors = [NSArray arrayWithObject: sorter];
[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Handle you error here
}
[sorter release];
[myTableView reloadData];
Это был самый простой способ для меня справиться с изменением сортировки "на лету", не отбрасывая FRC или не делая никаких других причудливых объектов. Я не уверен, что это повлияет на производительность, и это может повлиять, если набор строк в таблице огромен.
Ответ 2
Вместо использования NSFetchedResultsController в качестве источника данных для представления таблицы создайте NSArray, который вы устанавливаете, когда пользователь меняет порядок сортировки с помощью сегментарного элемента управления, основывая содержимое массива на полученных результатах. Затем просто сортируйте, используя стандартную сортировку массива. Что-то вроде этого:
- (IBAction)segmentChanged:(id)sender
{
// Determine which segment is selected and then set this
// variable accordingly
BOOL ascending = ([sender selectedSegmentIndex] == 0);
NSArray *allObjects = [fetchedResultsController fetchedObjects];
NSSortDescriptor *sortNameDescriptor =
[[[NSSortDescriptor alloc] initWithKey:@"name"
ascending:ascending] autorelease];
NSArray *sortDescriptors = [[[NSArray alloc]
initWithObjects:sortNameDescriptor, nil] autorelease];
// items is a synthesized ivar that we use as the table view
// data source.
[self setItems:[allObjects sortedArrayUsingDescriptors:sortDescriptors]];
// Tell the tableview to reload.
[itemsTableView reloadData];
}
Таким образом, дескриптор сортировки, который я использовал, называется "имя", но вы должны изменить его на имя поля, которое вы хотите отсортировать, в полученных результатах. Кроме того, элементы ivar, на которые я ссылался, будут вашим новым источником данных в виде таблицы. Теперь ваши делегаты в представлении таблицы будут выглядеть примерно так:
- (NSInteger)tableView:(UITableView*)tableView
numberOfRowsInSection:(NSInteger)section
{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get your table cell by reuse identifier as usual and then grab one of
// your records based on the index path
// ...
MyManagedObject *object = [items objectAtIndex:[indexPath row]];
// Set your cell label text or whatever you want
// with one of the managed object fields.
// ...
return cell;
}
Не уверен, что это лучший способ, но он должен работать.
Ответ 3
Ответ Андреаса Шефера работал у меня. Трюк устанавливает новый параметр для запроса выборки с тем, является ли он этим кодом:
[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];
ИЛИ
[[fetchedResultsController fetchRequest] setPredicate:predicate];
Прежде чем называть это:
if (![[self fetchedResultsController] performFetch:&error]) {
// Handle you error here
}
[self.tableView reloadData];
кажется, что когда вы устанавливаете новый параметр, NSFetchedResultsController будет выполнять новый fetchrequest на основе того, что вы установили. Не устанавливая новый параметр, он не будет выполнять повторную выборку и просто вызывает performFetch
it не будет работать.
Надеюсь, это поможет кому-то еще.
Ответ 4
fetchRequest
- свойство только для чтения. Строка кода в вашем сообщении не будет работать. Если вы хотите использовать другой запрос на выборку, вам нужно будет заменить ваш контроллер новым NSFetchedResultsController
. Ваша таблица не будет перезагружаться автоматически. Вам потребуется отправить сообщение reloadData
через некоторое время после замены NSFetchedResultsController
.