Не удается получить результат Realm для объектов, отфильтрованных по последнему значению (nsdate) свойства свойства коллекции swift (пример более понятен) - PullRequest
0 голосов
/ 19 марта 2020

У меня есть следующая модель

class Process: Object {
    @objc dynamic var processID:Int = 1
    let steps = List<Step>()
}

class Step: Object {
    @objc private dynamic var stepCode: Int = 0
    @objc dynamic var stepDateUTC: Date? = nil
    var stepType: ProcessStepType {
        get {
            return ProcessStepType(rawValue: stepCode) ?? .created
        }
        set {
            stepCode = newValue.rawValue
        }
    }
}

enum ProcessStepType: Int { // to review - real value
    case created = 0
    case scheduled = 1
    case processing = 2
    case paused = 3
    case finished = 4
}

Процесс может запускаться, обрабатываться, приостанавливаться, возобновляться (для повторной обработки), приостанавливаться, возобновляться снова и т. Д. c. текущий шаг - это последний шаг stepDateUT C

Я пытаюсь получить все процессы, имеющие для последнего шага шаг обработки stepType «обработка», ie. где для последнего шага stepDode, stepCode равен 2. Я пришел со следующим предикатом ... который не работает. Любая идея, как правильно выполнить такой запрос?

Моё лучшее испытание - одно. Можно ли получить этот результат с помощью одного запроса области?

let processes = realm.objects(Process.self).filter(NSPredicate(format: "ANY steps.stepCode = 2 AND NOT (ANY steps.stepCode = 4)")

let ongoingprocesses = processes.filter(){$0.steps.sorted(byKeyPath: "stepDateUTC", ascending: false).first!.stepType == .processing}

то, что я надеялся, сработает

NSPredicate(format: "steps[LAST].stepCode = \(TicketStepType.processing.rawValue)")

Я понимаю, что [LAST] не поддерживается сферой (согласно чит-листу). но разве я смог достичь своей цели с помощью запроса области?

1 Ответ

0 голосов
/ 22 марта 2020

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

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

let results = realm.objects(Process.self).filter { p in
    let lastIndex = p.steps.count - 1
    let step = p.steps[lastIndex]
    let type = step.stepType
    if type == .processing {
        return true
    }
    return false
}

Обратите внимание, что объекты Realm загружаются лениво - это означает, что тысячи объектов оказывают незначительное влияние на память. Фильтруя с помощью Swift, объекты фильтруются в памяти, поэтому влияние оказывается более значительным.

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

class Process: Object {
    @objc dynamic var processID:Int = 1
    let stepHistory = List<Step>() //RENAMED: the history of the steps
    @objc dynamic var name = ""

    //ADDED: new property tracks current step
    @objc dynamic var current_step = ProcessStepType.created.index 
}

Моя мысль заключается в том, что модель Процесса хранит «историю» шагов, которые были выполнены до этого момента, а затем значение current_step.

Я также изменил ProcessStepType enum, чтобы сделать его более удобным для фильтрации.

enum ProcessStepType: Int { // to review - real value
    case created = 0
    case scheduled = 1
    case processing = 2
    case paused = 3
    case finished = 4

    //this is used when filtering
    var index: Int {
        switch self {
        case .created:
            return 0
        case .scheduled:
            return 1
        case .processing:
            return 2
        case .paused:
            return 3
        case .finished:
            return 4
        }
    }
}

Затем, чтобы вернуть все процессы, где последний шаг в списке - это «обработка», вот фильтр

let results2 = realm.objects(Process.self).filter("current_step == %@", ProcessStepType.processing.index)

Последняя мысль: добавьте некоторый код в модель Process, чтобы при добавлении шага в список переменная current_step также обновлялась. Кодирование, оставленное для OP.

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