Можно ли создать предикат на основе свойств объектов дочернего класса? - PullRequest
0 голосов
/ 24 января 2019

У меня есть два класса: активность и действие. Activity - родительский класс, Action - дочерний, это отношение один ко многим. При настройке NSFetchedResultsController я хотел бы установить предикат на основе свойств дочернего класса. Вот пример ...

fetchRequest.predicate = NSPredicate(format: "filter only activities that have actions which have their date property equalling today")

Если бы я фильтровал действия, используя цикл for, это было бы так ...

for activity in activities
{
    if activity.actions != nil
    {
        for action in activity.actions
        {
            if action.date == today
            {
                // add activity to filtered array
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Какие-нибудь действия сегодня? Формат предиката:

"ANY actions.date == today"
0 голосов
/ 24 января 2019

Вы можете использовать SUBQUERY в вашем NSPredicate.Здесь я использовал NSArray в качестве демонстрации.

let today = Date()

let array: NSArray = [
    Activity(actions: [
        Action(date: today)
        ]),
    Activity(actions: [
        Action(date: Date(timeIntervalSince1970: 0))
        ])
]

// here is your predicate
let result = array.filtered(using: NSPredicate(format: "SUBQUERY(actions, $action, $action.date == %@) .@count > 0", today as CVarArg))
print(result.count) // 1

Обратите внимание, что я использовал == здесь для сравнения дат, что означает, что он будет совпадать только в том случае, если дата равна точно равно today.Если под «сегодня» вы имели в виду «любое время из 24 часов», то вам придется использовать ответ, предложенный в этом вопросе :

func getLastAndNextMidnight(date: Date) -> (Date, Date) {
    let dateComponents = Calendar.current.dateComponents([.year, .month, .day], from: date)
    var oneDay = DateComponents()
    oneDay.day = 1
    let lastMidnight = Calendar.current.date(from: dateComponents)!
    let nextMidnight = Calendar.current.date(byAdding: oneDay, to: lastMidnight)!
    return (lastMidnight, nextMidnight)
}
let midnights = getLastAndNextMidnight(date: today)
let result = array.filtered(using: NSPredicate(format: "SUBQUERY(actions, $action, ($action.date >= %@) AND ($action.date <= %@)) .@count > 0", midnights.0 as CVarArg, midnights.1 as CVarArg))
print(result.count)
...