Подтвердить что ты не робот

Изменение сортировки в NSFetchedResultsController на лету

Я пытаюсь изменить сортировку в NSFetchController "на лету", каким-то сегментированным элементом управления. Для сортировки типа A- > Z Z- > A.

Что мне нужно сделать, чтобы сделать это? Я следую примеру Джеффа Ламархе: Здесь

Мне нужно создать новый NSFetchedResultsController, а затем установить его или просто создать новый NSFetchRequest и сделать

fetchedResultController.fetchRequest = newFetchRequest

а затем моя таблица будет автоматически обновляться?

4b9b3361

Ответ 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.