基于核心数据中基础实体属性的计算属性

时间:2017-10-16 16:56:06

标签: swift core-data

我有一个核心数据模型,实体“Day”包含零个或多个“Workout”。日实体具有许多属性,这些属性通过对所有锻炼进行求和来计算。例如,totalKM将所有锻炼的km属性值相加。

我无法让它发挥作用。

我可以通过覆盖值(forKey)方法来显示总计:

public override func value(forKey key: String) -> Any? {
    if(key == "swimSeconds"){
        var swimSeconds: Int64 = 0
        if let array = workouts?.allObjects{
            for w in array{
                let workout: Workout = w as! Workout
                if (workout.sport == Workout.SPORT.Swim.rawValue){
                    swimSeconds += workout.seconds
                }
            }
        }
        return swimSeconds
    }else{
        return super.value(forKey: key)
    }
}

然而,这意味着如果基础锻炼被更改,则不会反映在日实体中显示的总值中。此外,感觉这不是正确的事情 - 我不应该覆盖这种方法。

我尝试使用Xcode创建NSManagedObject子类,但是它创建了一个包含所有@NSManaged变量的扩展,但这只会产生大量错误“Extensions可能不包含存储的属性”,这只能通过删除@NSManaged来解决。

我尝试创建自己的Extension to Day并拥有一个只有getter的属性:

var totalSwimSeconds: Int64{
    get{
        var swimSeconds: Int64 = 0
        if let array = workouts?.allObjects{
            for w in array{
                let workout: Workout = w as! Workout
                if (workout.sport == Workout.SPORT.Swim.rawValue){
                    swimSeconds += workout.seconds
                }
            }
        }
        return swimSeconds
    }
}

此方法产生运行时错误: 实体日不是密钥“totalSwimSeconds”

的密钥值编码兼容

我在线搜索是否可以找到这样的示例,但所有示例都只是在给定实体中组合属性的简单情况(例如,来自DOB的年龄,名字和姓氏的全名)更复杂的计算,查看其他实体中包含的属性。

如何在核心数据中创建计算属性,该属性将从基础实体计算并在更新时进行更新?

[我在Swift 4中使用Xcode 9]

1 个答案:

答案 0 :(得分:3)

在Swift 4中添加属性@objcdynamic以使计算属性键值编码符合。

@objc dynamic var totalSwimSeconds: Int64 { ...

编辑:

观察workouts

中的keyPathsForValuesAffectingValue属性覆盖Day
override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
    switch key {
    case "totalSwimSeconds": return Set(["workouts"])
    default: return super.keyPathsForValuesAffectingValue(forKey:key)
    }
}