【问题标题】:Is there a way to use a computed property with a parameter in Core Data?有没有办法在 Core Data 中使用带有参数的计算属性?
【发布时间】: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 类型,这样我就不必在每次需要时将天数转换为日期。所以我必须通过添加两个新字段startDaysstartWeeks 来对表进行非规范化,并使用您的方法进行计算。由于非规范化,这不是最好的解决方案,但我想这是唯一的方法。谢谢!如果您愿意,您可以将此作为答案发布,我会接受。
  • 也许你可以把这一切都作为一天的计算——例如重复周期仅为 7 天。

标签: swift core-data database-design nsmanagedobject transient


【解决方案1】:

要解决此问题,您可以将数据存储为标量类型,然后在谓词中进行简单的算术运算。不要使用日期,而是使用具有从零开始的天数的整数(或这些计算所需的任何最小时间单位)。将您的重复周期存储为天数。

然后您可以在谓词中使用计算((searchDate - startDate) mod repeatCycle) == 0 来查找匹配的类。

正如您所建议的,对不同搜索案例的数据进行非规范化可能是明智的。

【讨论】:

    猜你喜欢
    • 2021-12-08
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 2021-07-19
    相关资源
    最近更新 更多