我有一个核心数据模型,其实体 \xe2\x80\x9cDay\xe2\x80\x9d 包含零个或多个 \xe2\x80\x9cWorkout\xe2\x80\x9ds。日实体具有许多属性,这些属性是通过对所有锻炼进行求和来计算的。例如,totalKM 将所有锻炼的 km 属性值相加。
\n\n我只能 \xe2\x80\x99t 让它工作。
\n\n我可以通过重写 value(forKey) 方法来显示总计:
\n\npublic override func value(forKey key: String) -> Any? {\n if(key == "swimSeconds"){\n var swimSeconds: Int64 = 0\n if let array = workouts?.allObjects{\n for w in array{\n let workout: Workout = w as! Workout\n if (workout.sport == Workout.SPORT.Swim.rawValue){\n swimSeconds += workout.seconds\n }\n }\n }\n return swimSeconds\n }else{\n return super.value(forKey: key)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然而,这意味着如果基础锻炼发生变化,这不会反映在“日”实体中显示的总计值中。而且感觉这不是正确的做法 - 我不应该\xe2\x80\x99t需要覆盖这个方法。
\n\n我\xe2\x80\x99ve尝试使用Xcode创建NSManagedObject子类,但这创建了一个包含所有@NSManaged变量的扩展,但这只会给出大量错误\xe2\x80\x9cExtensions可能不包含存储的属性\xe2\x80\x9d仅通过删除@NSManaged 来修复。
\n\n我尝试创建自己的 Extension to Day 并拥有一个只有 getter 的属性:
\n\nvar totalSwimSeconds: Int64{\n get{\n var swimSeconds: Int64 = 0\n if let array = workouts?.allObjects{\n for w in array{\n let workout: Workout = w as! Workout\n if (workout.sport == Workout.SPORT.Swim.rawValue){\n swimSeconds += workout.seconds\n }\n }\n }\n return swimSeconds\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n此方法会产生以下运行时错误:\nentity Day 与键“totalSwimSeconds”的键值编码不兼容
\n\nI\xe2\x80\x99ve 在线搜索,看看是否可以找到这样的示例,但所有示例都只是给定实体内组合属性的简单情况(例如出生日期的年龄、名字和姓氏的全名)查看其他实体中包含的属性的更复杂的计算。
\n\n如何在核心数据中创建计算属性,该属性将从基础实体计算并在更新时更新?
\n\n[我正在使用 Xcode 9 和 Swift 4]
\n在 Swift 4 中添加属性@objc和dynamic以使计算属性键值编码兼容。
@objc dynamic var totalSwimSeconds: Int64 { ...
Run Code Online (Sandbox Code Playgroud)
编辑:
观察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)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1940 次 |
| 最近记录: |