这可能是一个奇怪的问题,因为我不完全了解瞬态和新派生的属性如何在Core Data中工作。因此,假设我有一个RegularClass
实体,该实体存储随时间重复的任何类。例如,每三天或每星期重复一次课程。这就是它在数据模型中的样子:
((RegularClass
属于Schedule
实体,而该实体又属于Course
实体)
[现在,如果我们的类每三天重复一次,我们将数字3存储在frequency
属性中,并将字符串"days"
存储在unit
属性中,然后在Swift中将其转换为枚举。每个Schedule
所属的RegularClass
具有startDate
属性。
[要检查某个班级是否在给定日期发生,我想出的最好方法就是计算unit
和给定日期之间指定的startDate
的差,然后取差和频率之间的余数,如果它是0,而不是可以上课的日期。
var differenceComponent: Calendar.Component {
switch unitType {
case .weeks:
return .weekOfYear
case .days:
return .day
}
}
func getDifferenceFromDateComponents(_ dateComponents: DateComponents) -> Int? {
switch unitType {
case .weeks:
return dateComponents.weekOfYear
case .days:
return dateComponents.day
}
}
func dateIsInActiveState(_ date: Date) -> Bool {
if let startDate = schedule?.startDate {
let comps = Calendar.current.dateComponents([differenceComponent], from: startDate, to: date)
if let difference = getDifferenceFromDateComponents(comps) {
let remainder = Int64(difference) % frequency // that is the key!
return remainder == 0
}
}
return false
}
func containsDate(_ date: Date) -> Bool {
if dateIsInActiveState(date) {
if unitType == .days {
return true
}
let weekday = Calendar.current.component(.weekday, from: date)
return (weekdays?.allObjects as? [Weekday])?.contains(where: { $0.number == weekday }) ?? false
}
return false
}
现在,事情是这段代码非常适合我从获取请求中获得的课程。但是,是否有一种方法可以在请求发生时在NSPredicate
中传递日期参数来进行计算?还是我必须获取所有课程,然后手动将其过滤掉?
要解决此问题,您可以将数据存储为标量类型,然后在谓词中执行简单的算术运算。而不是日期,而应使用具有从零开始的天数(或这些计算所需的最小时间单位)的整数。将重复周期存储为天数。
然后您可以在谓词中使用计算((searchDate - startDate) mod repeatCycle) == 0
查找匹配的类。
正如您所建议的,针对不同的搜索案例对数据进行非规范化可能是明智的。