Swift:根据日期对获取时的Core Data子实体进行排序 [英] Swift: Sorting Core Data child entities on fetch based on Date
问题描述
我正在制作一个日历应用程序,使用Core Data在其中存储事件.
I'm making a calendar app in which I store events using Core Data.
它由以下组成:DateKey
作为CalendarEventModel
的父级(具有一对多关系).概念是DateKey
保留yyyy-dd-MM日期字符串,并且当天发生的所有事件都作为子代作为子代添加到NSOrderedSet中的CalendarEventModel
中. (我使用的是类定义",没有一个实体是抽象的.) CalendarEventModel是包含有关一个日历事件的信息的实体.
Its composed of: DateKey
as the parent (with a one-to-many relationship) to CalendarEventModel
. The concept is that DateKey
holds a yyyy-dd-MM date string and all events that occur that day are added as a child to that DateKey
as CalendarEventModel
in a NSOrderedSet. (I'm using Class Definition, none of the entities are abstract.). CalendarEventModel being the entity containing information about one calendar event.
我要完成的任务
一切都按预期进行,除了我无法对获取的结果进行排序.当我获取与当前日历相关的DateKeys时,我简直无法让它们像这样进行排序:
Everything works as intended except that I can't sort my fetched results. When I fetch the DateKeys relevant for the current Calendar I simply can't get them to sort like this:
我想对CalendarEventModels属性startDate
之后的每个DateKey中的CalendarEventModel进行升序排序($ 0.startDate< $ 1.startDate).然后,在带有isAllDay = true
的CalendarEventModels之前标记为isAllDay = false
.
I want to sort the CalendarEventModel in each DateKey after the CalendarEventModels attribute startDate
in ascending order ($0.startDate < $1.startDate). Then have the CalendarEventModels marked isAllDay = false
before those with isAllDay = true
.
问题/问题
- 在下面的代码中,我在注释中做了一些澄清.
- 我无法让NSSortDescriptor正常工作(我的尝试在下面的代码中得到注释
- 我已经了解了DateKey的
calendarEvents
属性是NSOrderedSet,但是我还没有找到如何将其用于排序标准.
- I've put some clarifications in comment in the code below.
- I can't get NSSortDescriptor to work properly ( my attempt is commented in the code below
- I've read about NSOrderedSet which the
calendarEvents
attribute of DateKey is, but I haven't found out how to use it for my sorting criteria.
您将如何解决这种排序? 让我知道是否需要更多信息.
How would you solve this sorting? Let me know if more information is needed.
我的代码
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 MM dd"
或-强烈建议-Date
类型的字符串格式对日期进行排序. - 您无法对关系进行分类.一对多关系是无序的
Set
.顺便说一句,将关系声明为本机Set<CalendarEventModel>
而不是未指定的NSSet
且为非可选. - 不要使用复合谓词,使用一个谓词,不要获取
DateKey
记录,不要获取具有谓词dateKey.dateInfo >= startDate && dateKey.dateInfo <= endDate
的CalendarEventModel
记录,并在其中添加两个排序描述符./li>
- Basically you cannot sort dates in string format
"yyyy dd MM"
, either use"yyyy MM dd"
or – highly recommended –Date
type. - You cannot sort a relationship in place. To-many relationships are
Set
s which are unordered. By the way declare the relationship as nativeSet<CalendarEventModel>
rather than unspecifiedNSSet
and as non-optional. - Don't use a compound predicate, use one predicate and don't fetch
DateKey
records, fetchCalendarEventModel
records with predicatedateKey.dateInfo >= startDate && dateKey.dateInfo <= endDate
and add there the two sort descriptors.
一次获取经过过滤和排序的记录比获取关系项并手动对其进行排序要有效得多.
Fetching filtered and sorted records once is much more efficient than get the relationship items and sort them manually.
要获取今天的午夜和+ 9天的使用时间
To get midnight of today and + 9 days use
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]]
字典
This code fetches all sorted CalendarEventModel
in the date range and groups the array to a [Date : [CalendarEventModel]]
dictionary
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
块之后不要执行 good 代码.提取后,将所有 good 代码放入do
范围.
Don't execute good code after the catch
block. Put all good code in the do
scope after the fetch.
这篇关于Swift:根据日期对获取时的Core Data子实体进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!