Есть ли способ использовать вычисляемое свойство с параметром в Core Data? - PullRequest
0 голосов
/ 31 октября 2019

Это может быть странный вопрос, потому что я не до конца понимаю, как переходные и новые производные свойства работают в Core Data. Итак, представьте, что у меня есть сущность RegularClass, которая хранит любой класс, который повторяется с течением времени. Класс может повторяться, например, каждый третий день или каждую неделю. Вот как это выглядит в модели данных:

data model for RegularClass

(RegularClass принадлежит сущности Schedule, которая, в свою очередь, принадлежитCourse entity)

Теперь, если наш класс повторяется каждый третий день, мы сохраняем число 3 в свойстве frequency и строку "days" в свойстве unit, которое затем преобразуется вперечисление в Swift. Schedule, которому принадлежит каждый RegularClass, обладает свойством startDate.

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

var differenceComponent: Calendar.Component {
    switch unitType {
    case .weeks:
        return .weekOfYear
    case .days:
        return .day
    }
}

func getDifferenceFromDateComponents(_ dateComponents: DateComponents) -> Int? {
    switch unitType {
    case .weeks:
        return dateComponents.weekOfYear
    case .days:
        return dateComponents.day
    }
}

func dateIsInActiveState(_ date: Date) -> Bool {
    if let startDate = schedule?.startDate {
        let comps = Calendar.current.dateComponents([differenceComponent], from: startDate, to: date)
        if let difference = getDifferenceFromDateComponents(comps) {
            let remainder = Int64(difference) % frequency // that is the key!
            return remainder == 0
        }
    }
    return false
}

func containsDate(_ date: Date) -> Bool {
    if dateIsInActiveState(date) {
        if unitType == .days {
            return true
        }

        let weekday = Calendar.current.component(.weekday, from: date)
        return (weekdays?.allObjects as? [Weekday])?.contains(where: { $0.number == weekday }) ?? false
    }

    return false
}

Теперь, дело в том, что этот код отлично работает для курсов, которые я уже получил из запроса на выборку. Но есть ли способ передать параметр даты в NSPredicate, чтобы вычислить это во время запроса? Или мне нужно выбрать все курсы, а затем отфильтровать их вручную?

1 Ответ

1 голос
/ 03 ноября 2019

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

Затем вы можете использовать вычисление ((searchDate - startDate) mod repeatCycle) == 0 в своем предикате для поиска подходящих классов.

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

...