Сортировка CoreData по отношению ко многим

Я пишу приложение для iOS, в котором есть хранилище личных записей, и ему нужно отображать списки, отсортированные определенным образом. Существует переменное количество этих порядков, и они генерируются «на лету», но я бы хотел, чтобы они хранились в хранилище данных. SQL-способ сделать это - иметь таблицу ListPositions с именем списка, идентификатором в таблице лиц и ключом сортировки. Затем, чтобы отобразить конкретный список, я могу выбрать все ListPositions списка с заданным именем, вытащить упомянутых лиц и отсортировать по ключу сортировки. Пытаюсь сделать это в CoreDatat, но сталкиваюсь с проблемами. Я пытаюсь сделать это, используя такую ​​схему:

Person:
    Name
    DOB
    etc... 
    positions -->> ListPosition

ListPosition:
    listName
    sortKey
    person --> Person

Затем я могу получить всех лиц в данном списке с помощью NSPredicate [NSPredicate predicateWithFormat:@"ANY positions.listName like %@", someList];. Это позволяет мне динамически добавлять списки для большого набора лиц. Проблема в том, что я не могу использовать поле sortKey ListPosition для сортировки лиц. Какой NSSortDescriptor это сделает? И если невозможно отсортировать выборку по свойству одного элемента отношения ко многим, каков еще один способ получить несколько динамических порядков в coredata? Я показываю списки с помощью NSFetchedResultsController, поэтому я не могу собрать списки самостоятельно в памяти. Мне нужно сделать это с помощью одного NSFetchRequest.


person wombat57    schedule 06.02.2011    source источник
comment
Некоторое более приятное форматирование облегчило бы чтение вашего вопроса.   -  person vikingosegundo    schedule 06.02.2011


Ответы (5)


Вы правы - после отношения ко многим возвращается NSSet, который не имеет встроенной сортировки. Чтобы получить отсортированные результаты, есть несколько вариантов:

  1. Предполагая, что Person / ListPosition является двусторонней связью, выполните новый запрос на выборку для сущностей ListPosition. Сделайте совпадение предиката для отношения "человек" из ListPosition, которое будет выглядеть примерно как [NSPredicate predicateWithFormat:@"person=%@", myPerson]. Используйте любой дескриптор сортировки, который вам нужен в запросе на выборку.
  2. Следите за отношениями, когда вы это делаете, что дает вам NSSet. Затем используйте метод -sortedArrayUsingDescriptors: NSSet, чтобы преобразовать его в отсортированный массив.
person Tom Harrington    schedule 06.02.2011
comment
Мне было непонятно. Моя проблема не в том, как отсортировать объекты по отношению ко многим, а скорее в том, как обеспечить множество различных порядков сортировки для большого набора объектов. Я редактировал вопрос. - person wombat57; 07.02.2011

Я думаю, что лучшим подходом в этом случае было бы получение вместо этого объекта ListPosition. Добавьте дескриптор сортировки для sortKey (он будет работать в этом случае, потому что запрос выборки находится в сущности ListPosition) и предварительно выберите Person, связанный с именем списка, используя setRelationshipKeyPathsForPrefetching для «человека» в запросе выборки.

[NSPredicate predicateWithFormat:@"listName like %@", someList];
person siasl    schedule 13.09.2012
comment
Это работает, однако, если вы внесете какие-либо изменения в объект Person, это не вызовет обновление NSFetchedResultsController, поскольку ListPosition не изменилось. - person Andrew Theis; 29.07.2014

Если я правильно понимаю вашу модель, каждый Person имеет по одному ListPosition для каждого списка, в котором он участвует. Допустим, у нас есть список рассылки по их именам, поэтому у X человек есть позиции в списке X с одинаковыми listName и sortKey.

Я бы создал объект List, который бы содержал атрибут sortKey, а затем использовал бы его в дескрипторе сортировки.

entity List:
    - sortKey : string
    - ascending : bool

Создайте дескриптор сортировки и используйте его в запросе на выборку:

[NSSortDescriptor sortDescriptorWithKey:chosenList.sortKey ascending:chosenList.ascending];

Тогда у вас может быть столько списков, сколько вы хотите, и вы можете легко использовать его ключ сортировки для сортировки всех людей.


Если вы хотите сохранить позиции в базе данных (вы не упомянули атрибут index в своем ListPosition или что-то подобное), вы можете создать «совместный объект»:

entity PersonInList:
    - index : integer
    - person -> Person
    - list –> List

Другая идея - упорядочить набор Person объектов прямо в List сущности.

person Tricertops    schedule 29.11.2012

Получите ListPosition (он будет NSMutableSet). Затем выполните сортировку на Set, например:

NSMutableSet *positionsSet = [personEntity mutableSetValueForKey:@"positions"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"yourSortKey" ascending:NO];
NSArray *positionsSortedSet = [positionsSet sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

Это даст вам отсортированный массив в соответствии с вашим ключом.

person HeavenlyManBR    schedule 18.12.2013

Обычно я добавляю к объекту поле индекса (тип NSNumber). При добавлении товара очень просто рассчитать индекс. просто по

object.index = person.positions.count

Итак, на самом деле вам не нужно поле позиций, а отношение позиций. подключить физическое лицо к объекту ListPosition будет достаточно.

person Jerry Juang    schedule 24.07.2013