Сортировка CoreData по отношению ко многим - PullRequest
13 голосов
/ 06 февраля 2011

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

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

ListPosition:
    listName
    sortKey
    person --> Person

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

Ответы [ 5 ]

3 голосов
/ 07 февраля 2011

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

  1. Предполагая, что Person / ListPosition является двусторонним отношением, выполните новый запрос на выборку для объектов ListPosition.Установите соответствие предиката для отношения "person" из ListPosition, которое будет выглядеть примерно как [NSPredicate predicateWithFormat:@"person=%@", myPerson].Используйте любой дескриптор сортировки, который вам нужен в запросе на выборку.
  2. Следуйте отношениям, которые вы делаете, что дает вам NSSet.Затем используйте метод NSSet -sortedArrayUsingDescriptors:, чтобы преобразовать его в отсортированный массив.
1 голос
/ 19 декабря 2013

Получить ListPosition (оно будет называться NSMutableSet).Затем выполните сортировку на множестве следующим образом:

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

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

1 голос
/ 30 ноября 2012

Если я правильно понимаю вашу модель, у каждого 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 сущности.

1 голос
/ 13 сентября 2012

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

[NSPredicate predicateWithFormat:@"listName like %@", someList];
0 голосов
/ 24 июля 2013

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

object.index = person.positions.count

, поэтому на самом деле вам нужно не поле позиций, а отношение позиций.было бы достаточно соединить сущность лица с сущностью ListPosition.

...