繁体   English   中英

Swift:根据Date在fetch上对Core Data子实体进行排序

[英]Swift: Sorting Core Data child entities on fetch based on Date

介绍

我正在创建一个日历应用程序,我使用Core Data存储事件。

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

我试图完成的任务

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

我想在CalendarEventModels属性startDate之后按升序排序每个DateKey中的CalendarEventModel($ 0.startDate <$ 1.startDate)。 然后在具有isAllDay = true那些之前将CalendarEventModel标记为isAllDay = false

问题/问题

  • 我在下面的代码中对评论做了一些澄清。
  • 我无法让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!
}

感谢您阅读我的问题。

一些说明:

  • 基本上你不能用字符串格式"yyyy dd MM"来排序日期,使用"yyyy MM dd"或 - 强烈推荐 - Date类型。
  • 您无法对关系进行排序。 To-many关系是Set s,它们是无序的。 顺便说一下,将关系声明为本机Set<CalendarEventModel>而不是未指定的NSSet ,并且是非可选的。
  • 不要使用复合谓词,使用一个谓词并且不获取DateKey记录,使用谓词dateKey.dateInfo >= startDate && dateKey.dateInfo <= endDate获取CalendarEventModel记录,并在那里添加两个排序描述符。

获取过滤和排序的记录一次比获取关系项并手动排序更有效。

编辑:

今天午夜到+ 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作用域中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM