Есть ли способ в Realm реализовать order_by для вложенных объектов - PullRequest
1 голос
/ 15 мая 2019

Я пытаюсь получить вложенные объекты, отсортированные в определенном порядке, когда я получаю родительский объект с помощью realm.objects ().И не менее важно поддерживать порядок сортировки, если какой-либо вложенный объект был изменен.

Я искал связанные проблемы, но они либо устарели, либо не совсем проблема, которую я описываю

Вот пример: Iиметь 'user in Realm, у каждого из которых есть' задача (с лишними полями для ясности)

class task: Object {
    @objc dynamic var priority = 10
}

class user: Object {
    @objc dynamic var name = ""
    let tasks = List<task>()
}

Я создаю несколько пользователей, а затем добавляю задачи для любого данного пользователя (таблица в моем пользовательском интерфейсе с разделомдля каждого пользователя и задач для этого пользователя в виде строк в разделе этого пользователя, отсортированных по приоритету.

Приоритет по умолчанию начинается с 10 и может быть изменен в диапазоне от 1 до 10 в любое время.

Когда я получаю пользователей:

// (1)
users = realm.objects(user.self).sorted(byKeyPath: "name")

Я хочу получить их задачи, отсортированные по приоритету.

Обратите внимание, что приоритет изменяется после первоначального извлечения пользователей (это означает, что приоритет объекта задачи Results изменяется в realm.write ()).Чтобы уточнить, где-то в моем коде, для задачи данного пользователя, я делаю следующее:

realm.write() {
    task1.priority = newPriority
?

Это означает, что список задач пользователя всегда должен быть отсортирован по приоритету и не требует повторения (1) выше.Я не могу отсортировать свойство user.tasks, потому что это переменная let.

Обратите внимание, что и объекты пользователя, и задачи имеют порядок сортировки.

Я мог бы выполнить индексирование (удаление / добавление) для задач после того, как обновил «Приоритет» выше, но еще не попробовал это.Однако, вместо того, чтобы делать это вручную (и предполагая, что это работает, и предполагая, что не происходит удаления / добавления 'задачи', происходящей вместе с перестановкой, ...), разве не вся идея ORM состоит в том, чтобы сделать такоевсе просто?

В любом случае, чтобы сделать это?С расширениями на царство????Открыты для предложений по альтернативным подходам против вложенных объектов.

Ответы [ 2 ]

1 голос
/ 16 мая 2019

@ Ответ Джея, как всегда, велик, но я бы принял его предложение и сделал его неотъемлемым для объекта пользователя. Это мой «обычный» способ обработки требований, таких как этот.

Как вы говорите, свойство user object tasks является let, но именно так определяется объект Realm. Это не значит, что вы не можете добавить свои собственные вычисленные свойства для управления доступом к объекту.

Если вы хотите видеть только задачи в виде упорядоченного списка, добавьте свойство, которое дает вам это, например,

extension user
{
  var orderedTasks: Results<task>
  {
    return tasks.sorted(byKeyPath: "priority")
  }
}

Затем всегда используйте это свойство для доступа к задачам. Используя расширение, у меня есть собственный стиль - я просто сохраняю объявления данных в объявлении класса, а затем добавляю расширение с любыми вычисленными свойствами или функциями - но вы можете просто добавить объявление прямо в определение класса.

1 голос
/ 16 мая 2019

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

Повторяю вопрос

У пользователя есть задачи, и мы хотим работать с этими задачами в порядке список, и если есть изменения в заказе, сохраняйте их в порядке, указанном новым заказом

Используя два класса, представленных в вопросе, у нас есть кнопка, которая вызывает функцию для запроса области для пользователя и сохранения этого пользователя в классе var

var myUser: UserClass!

func loadUser() {
    if let realm = gGetRealm() { //my code to connect to Realm
        let userResults = realm.objects(UserClass.self)
        if userResults.count > 0 {
            let user = userResults[0]
            self.myUser = user
        }
    }
}

затем кнопка, которая вызывает функцию, чтобы просто распечатать задачи пользователей, упорядоченные по приоритету

func printOrderedTasks() {
    let sortedTasks = self.myUser.tasks.sorted(byKeyPath: "priority")
    for task in sortedTasks {
        print(task)
    }
}

Таким образом, для этого примера я создал 4 задачи, добавил их в список задач пользователя и записал пользователя в область. Первоначальный порядок приоритетов: 10, 0, 1, 4

Затем loadUser загружает и сохраняет первого доступного пользователя и назначает его классу var.

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

0
1
4
10

затем, используя Realm Studio, измените 1 на 6 и снова нажмите printOrderedTasks, и вы получите

0
4
6
10

без перезагрузки.

Объекты Realm обновляются в реальном времени, поэтому, если в вашем коде есть ссылка на них, любые изменения отражаются в реальном времени.

Вы можете расширить это, добавив наблюдателя к этому объекту, и Realm уведомит приложение о событии, к которому вы можете перезагрузить tableView или сообщить пользователю об изменении.

Edit:

Чтобы продвинуться дальше, пользовательские задачи также являются живыми объектами обновления, и если вы установите для них сортировку, эти результаты сохранят свою сортировку.

Например, давайте перепишем приведенный выше код, чтобы отслеживать задачи пользователей, которые поддерживают живую сортировку. Я переписал приведенный выше код, исключил пользовательский класс var и добавил класс задач var. Обратите внимание, что нам никогда не нужно повторно сортировать задачи, порядок сортировки устанавливается изначально, и они будут сортироваться с этого момента.

var myUserTasks: Results<TaskClass>!

func loadUserAndGetTasks() {
    if let realm = gGetRealm() {
        let userResults = realm.objects(UserClass.self)
        if userResults.count > 0 {
            let user = userResults[0]
            self.myUserTasks = user.tasks.sorted(byKeyPath: "priority")
        }
    }
}

func printTasks() {
    for t in self.myUserTasks {
        print(t)
    }
}

Первоначальный заказ был 10, 0, 1, 4, как указано выше. Если затем мы изменим 1 на шесть с помощью Realm Studio, а затем запустим функцию printTasks, вы увидите, что упорядочивание было выполнено автоматически, потому что результаты обновляются в реальном времени.

0
4
6
10

Крутая вещь в том, что вам не нужно продолжать прибегать к заданиям - они поддерживают порядок сортировки.

...