Изменение сортировки в NSFetchedResultsController на лету - PullRequest
17 голосов
/ 11 ноября 2009

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

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

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

fetchedResultController.fetchRequest = newFetchRequest

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

Ответы [ 4 ]

32 голосов
/ 12 сентября 2010

Я застрял с той же проблемой, и я мог ее исправить, просто установив дескрипторы сортировки в FetchRequest FetchRequestController, затем выполнив выборку (executeFetch) и, наконец, перезагрузил данные в табличном представлении.

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 или не обрабатывая любые другие необычные объекты. Я не уверен в том, что это повлияет на производительность, и это может повлиять, если количество строк в таблице будет огромным.

8 голосов
/ 12 ноября 2009

Вместо использования 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's fields.
    // ...

    return cell;
}

Не уверен, что это лучший способ, но он должен работать.

3 голосов
/ 30 января 2014

Андреас Шефер ответ работал для меня. Хитрость заключается в установке нового параметра для запроса на выборку с указанием следующего кода:

[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors];

OR

[[fetchedResultsController fetchRequest] setPredicate:predicate];

Перед вызовом это:

if (![[self fetchedResultsController] performFetch:&error]) {
        // Handle you error here
}

[self.tableView reloadData];

Похоже, что когда вы устанавливаете новый параметр, NSFetchedResultsController выполнит новый запрос на выборку в зависимости от того, что вы установили. Без установки нового параметра он не выполнит повторную выборку и просто вызовет performFetch не сработает ..

Надеюсь, это поможет кому-то еще ..

2 голосов
/ 11 ноября 2009

fetchRequest - свойство только для чтения. Строка кода в вашем посте не будет работать. Если вы хотите использовать другой запрос на выборку, вам нужно заменить свой контроллер новым NSFetchedResultsController. Ваша таблица не будет перезагружаться автоматически. Вам нужно будет отправить ему сообщение reloadData через некоторое время после замены NSFetchedResultsController.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...