有没有办法在 Core Data 中使用带有参数的计算 属性 ?
Is there a way to use a computed property with a parameter in Core Data?
这可能是一个奇怪的问题,因为我不完全理解 transient 和新的派生属性在 Core Data 中是如何工作的。
所以想象一下我有一个 RegularClass
实体,它存储随时间重复的任何 class。例如,class 可以每三天或每一周重复一次。这是它在数据模型中的样子:
(RegularClass
属于 Schedule
实体,后者又属于 Course
实体)
现在,如果我们的 class 每三天重复一次,我们将数字 3 存储在 frequency
属性 中,并将字符串 "days"
存储在 unit
属性,然后在 Swift 中转换为枚举。每个RegularClass
所属的Schedule
有一个startDate
属性。
为了检查 class 是否在给定日期发生,我没有比计算 startDate
和给定日期之间指定 unit
的差异更好的方法了,然后在差值和频率之间取余数,如果它是 0,那么它就是 class 可能发生的日期。
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: { [=11=].number == weekday }) ?? false
}
return false
}
现在,问题是这段代码非常适合我已经从获取请求中获得的课程。但是有没有一种方法可以在 NSPredicate
中传递日期参数来在请求发生时进行计算?或者我是否必须获取所有课程然后手动过滤掉它们?
要解决此问题,您可以将数据存储为标量类型,然后在谓词中进行简单的算术运算。而不是日期,使用具有从零开始的天数的整数(或这些计算所需的任何最小时间单位)。将您的重复周期存储为天数。
然后您可以在谓词中使用计算 ((searchDate - startDate) mod repeatCycle) == 0
来查找匹配项 类。
正如您所建议的,针对不同的搜索案例对数据进行非规范化处理可能是明智的。
这可能是一个奇怪的问题,因为我不完全理解 transient 和新的派生属性在 Core Data 中是如何工作的。
所以想象一下我有一个 RegularClass
实体,它存储随时间重复的任何 class。例如,class 可以每三天或每一周重复一次。这是它在数据模型中的样子:
(RegularClass
属于 Schedule
实体,后者又属于 Course
实体)
现在,如果我们的 class 每三天重复一次,我们将数字 3 存储在 frequency
属性 中,并将字符串 "days"
存储在 unit
属性,然后在 Swift 中转换为枚举。每个RegularClass
所属的Schedule
有一个startDate
属性。
为了检查 class 是否在给定日期发生,我没有比计算 startDate
和给定日期之间指定 unit
的差异更好的方法了,然后在差值和频率之间取余数,如果它是 0,那么它就是 class 可能发生的日期。
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: { [=11=].number == weekday }) ?? false
}
return false
}
现在,问题是这段代码非常适合我已经从获取请求中获得的课程。但是有没有一种方法可以在 NSPredicate
中传递日期参数来在请求发生时进行计算?或者我是否必须获取所有课程然后手动过滤掉它们?
要解决此问题,您可以将数据存储为标量类型,然后在谓词中进行简单的算术运算。而不是日期,使用具有从零开始的天数的整数(或这些计算所需的任何最小时间单位)。将您的重复周期存储为天数。
然后您可以在谓词中使用计算 ((searchDate - startDate) mod repeatCycle) == 0
来查找匹配项 类。
正如您所建议的,针对不同的搜索案例对数据进行非规范化处理可能是明智的。