【发布时间】:2019-10-31 09:07:02
【问题描述】:
这可能是一个奇怪的问题,因为我不完全了解瞬态和新派生属性在 Core Data 中的工作原理。
所以想象一下我有一个RegularClass 实体,它存储任何随时间重复的类。例如,可以每隔三天或一周重复一次课程。这是它在数据模型中的样子:
(RegularClass 属于Schedule 实体,而后者又属于Course 实体)
现在,如果我们的课程每三天重复一次,我们将数字 3 存储在 frequency 属性中,并将字符串 "days" 存储在 unit 属性中,然后在 Swift 中将其转换为枚举。每个RegularClass 所属的Schedule 具有startDate 属性。
为了检查课程是否在给定日期发生,我想出了比计算startDate 和给定日期之间指定unit 的差值更好的方法,然后在差值和频率之间取余数,然后如果为 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 中传递一个日期参数来计算这个?还是我必须获取所有课程然后手动过滤掉它们?
【问题讨论】:
-
这个答案:stackoverflow.com/a/36606137/978300 建议您可以在谓词中执行 mod,所以也许您可以将所有开始日期和频率存储为天然后搜索?
-
@Giles 我想过,但问题是我可能没有结束日期,所以我需要在数据库中存储无限数量的日期。
-
我认为,如果您将开始日期存储为 days-from-day-zero,并且您知道您的搜索日期为 days-from-day-zero,那么您应该能够在没有额外存储天数的谓词。搜索 - 开始 mod 重复
-
@Giles 嗯,这是一个好点!虽然我在这里也有几周,所以这意味着我还需要从零开始存储几周。而且我需要将
startDate保留为Date类型,这样我就不必在每次需要时将天数转换为日期。所以我必须通过添加两个新字段startDays和startWeeks来对表进行非规范化,并使用您的方法进行计算。由于非规范化,这不是最好的解决方案,但我想这是唯一的方法。谢谢!如果您愿意,您可以将此作为答案发布,我会接受。 -
也许你可以把这一切都作为一天的计算——例如重复周期仅为 7 天。
标签: swift core-data database-design nsmanagedobject transient