Swift:根据日期对提取的Core Data子实体进行排序

时间:2018-10-10 13:07:57

标签: ios swift sorting core-data

简介

我正在制作一个日历应用程序,使用Core Data在其中存储事件。

它由以下各项组成:DateKey作为CalendarEventModel的父项(具有一对多关系)。这个概念是DateKey保留一个yyyy-dd-MM日期字符串,并且当天发生的所有事件都作为子级添加为DateKey的子集,作为NSOrderedSet中的CalendarEventModel。 (我正在使用类定义,没有一个实体是抽象的。) CalendarEventModel是包含有关一个日历事件的信息的实体。

我要完成的任务

一切都按预期进行,除了我无法对获取的结果进行排序。当我获取与当前日历相关的DateKeys时,我简直无法让它们像这样进行排序:

我想对CalendarEventModels属性startDate之后的每个DateKey中的CalendarEventModel进行升序排序($ 0.startDate <$ 1.startDate)。然后,在带有isAllDay = false的CalendarEventModels之前标记为isAllDay = true

问题/问题

  • 我在下面的代码中添加了一些说明。
  • 我无法让NSSortDescriptor正常工作(我的尝试在下面的代码中注释了
  • 我已经了解了DateKey的calendarEvents属性是NSOrderedSet,但是我还没有找到如何将其用于排序标准。

您将如何解决这种排序? 让我知道是否需要更多信息。

我的代码

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 :(得分:0)

一些注意事项:

  • 基本上,您无法使用"yyyy dd MM"或-强烈建议使用-"yyyy MM dd"类型的字符串格式Date对日期进行排序。
  • 您无法对关系进行排序。一对多关系是Set,它们是无序的。顺便说一下,将该关系声明为本机Set<CalendarEventModel>而不是未指定的NSSet且为非可选关系。
  • 不要使用复合谓词,使用一个谓词,不要获取DateKey记录,不要获取带有谓词{{​​1}}的{​​{1}}记录并在其中添加这两个排序描述符。

一次获取经过过滤和排序的记录比获取关系项并手动对其进行排序要有效得多。

编辑:

要获取今天的午夜和+ 9天的使用时间

CalendarEventModel

此代码获取日期范围内所有已排序的dateKey.dateInfo >= startDate && dateKey.dateInfo <= endDate并将数组分组为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]]块之后不要执行 good 代码。提取后,将所有 good 代码放在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)") } 范围内。