Swift: сортировка дочерних сущностей базовых данных при получении на основе даты - PullRequest
0 голосов
/ 10 октября 2018

Введение

Я создаю приложение календаря, в котором я храню события с использованием Core Data.

Оно состоит из: DateKey в качестве родителя (с одним ко многимотношения) к CalendarEventModel.Концепция состоит в том, что DateKey содержит строку даты гггг-дд-ММ, и все события, которые происходят в этот день, добавляются как дочерние элементы к этому DateKey как CalendarEventModel в NSOrderedSet.(Я использую определение класса, ни одна из сущностей не является абстрактной.)CalendarEventModel - это сущность, содержащая информацию об одном событии календаря.

Что я пытаюсь выполнить

Все работает так, как задумано, за исключением того, что я не могу отсортировать полученные результаты.Когда я выбираю DateKeys, относящиеся к текущему календарю, я просто не могу заставить их сортировать так:

Я хочу отсортировать CalendarEventModel в каждом DateKey после атрибута CalendarEventModels startDate в порядке возрастания ($ 0.startDate <$ 1.startDate).Затем пометьте CalendarEventModels <code>isAllDay = false перед теми, у кого isAllDay = true.

Проблема / Вопрос

  • Я добавил некоторые пояснения в комментарии в кодениже.
  • Я не могу заставить NSSortDescriptor работать должным образом (моя попытка прокомментирована в приведенном ниже коде
  • Я читал о NSOrderedSet, которым является атрибут calendarEvents DateKey, но яЯ не нашел, как использовать его для моих критериев сортировки.

Как бы вы решили эту сортировку? Дайте мне знать, если потребуется дополнительная информация.

Мой код

fileprivate func loadEventsFromCoreData() {

    dateFormatter.dateFormat = "yyyy dd MM"
    let startDate = Date()
    var predicatesForFetch : [NSPredicate] = []
    var dateStringArray : [String] = []
    var fetchResultsArray : [DateKey]?

    for num in 0...9 {
        let newDate = startDate.add(TimeChunk(seconds: 0, minutes: 0, hours: 0, days: num, weeks: 0, months: 0, years: 0))
        let datePredicate = dateFormatter.string(from: newDate)
        dateStringArray.append(datePredicate)
        predicatesForFetch.append(NSPredicate(format: "dateInfo == %@", datePredicate))
    }
    setupSectionArray(eventArray: dateStringArray)

    // I'm getting the correct DateKeys and their events.

    let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicatesForFetch)
    let eventFetch : NSFetchRequest<DateKey> = DateKey.fetchRequest()
    eventFetch.predicate = compoundPredicate

    // I've tried specifying this sortDescriptor and added it to the eventFetch: 
    //   let descriptor = NSSortDescriptor(key: "calendarEvents", ascending: true) { ($0 as! CalendarEventModel).startDate!.compare(($1 as! CalendarEventModel).startDate!) }
    //   let sortDescriptors = [descriptor]
    //   eventFetch.sortDescriptors = sortDescriptors

        do {
            fetchResultsArray = try coreDataContext.fetch(eventFetch)

        } catch {
            print("Core Data initial fetch failed in Calendar Controller: \(error)")
        }

    guard fetchResultsArray != nil else { return }

    // Xcode doesn't recognize the .sort() function which does not have a return value... and I don't think its a good idea to use the return function at all since I will have to delete all children and re add the sorted for each fetch.

    for eventArray in fetchResultsArray! {
        eventArray.calendarEvents?.sorted(by: { ($0 as! CalendarEventModel).startDate!.compare(($1 as! CalendarEventModel).startDate!) == .orderedAscending })
        eventArray.calendarEvents?.sorted { ($0 as! CalendarEventModel).isAllDay && !($1 as! CalendarEventModel).isAllDay }

    }

    events = fetchResultsArray!
}

Спасибо, что прочитали мой вопрос.

1 Ответ

0 голосов
/ 10 октября 2018

Некоторые примечания:

  • Как правило, вы не можете сортировать даты в строковом формате "yyyy dd MM", либо используйте "yyyy MM dd", либо - настоятельно рекомендуется - Date.
  • Невозможно отсортировать отношения на месте.Отношения ко-многим являются Set s, которые неупорядочены.Кстати, объявляйте отношения как родные Set<CalendarEventModel>, а не как неопределенные NSSet и как необязательные.
  • Не используйте составной предикат, используйте один предикат и не извлекайте DateKey записей, извлекайте CalendarEventModel записей с предикатом dateKey.dateInfo >= startDate && dateKey.dateInfo <= endDate и добавляйте туда два дескриптора сортировки.

Один раз получить отфильтрованные и отсортированные записи гораздо эффективнее, чем получить элементы отношений и отсортировать их вручную .

Редактировать:

Чтобы получить полночь сегодняшнего дня и + 9 дней, используйте

let calendar = Calendar.current
let now = Date()
let nowPlus9Days = calendar.date(byAdding: .day, value: 9, to: now)!
let startDate = calendar.startOfDay(for: now)
let endDate = calendar.startOfDay(for: nowPlus9Days)

Этот код выбирает все отсортированные CalendarEventModel в диапазоне дат и группирует массив в словарь [Date : [CalendarEventModel]]

let predicate = NSPredicate(format: "dateKey.dateInfo >= %@ && dateKey.dateInfo <= %@", startDate as CVarArg, endDate as CVarArg)
let sortDescriptors = [NSSortDescriptor(key: "startDate", ascending: true), NSSortDescriptor(key: "isAllDay", ascending: true)]

let eventFetch : NSFetchRequest<CalendarEventModel> = CalendarEventModel.fetchRequest()
eventFetch.predicate = predicate
eventFetch.sortDescriptors = sortDescriptors
do {
    let fetchResultsArray = try coreDataContext.fetch(eventFetch)
    let groupedDictionary = Dictionary(grouping: fetchResultsArray, by: {$0.startDate})

} catch {
    print("Core Data initial fetch failed in Calendar Controller: \(error)")
}

Не выполнять хороший код после блока catch.Поместите весь хороший код в область действия do после извлечения.

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