我有一个连接到Storyboard GUI的核心数据模型。(Xcode 9和SWIFT 4)我现在想要添加一个源自另外两个属性的属性。我有一个名为Workout的实体,它的两个属性“rpe”和“秒”组合起来创建一个新属性“rpeTSS”。我在我的核心数据模型中声明了“repTSS”作为属性。我把它设置为瞬态。
我尝试在编辑器菜单下使用“make NSManagedObject subclass ...”选项,但这似乎产生了有错误的文件。我尝试了子类化生成的Workout类,但无法弄清楚如何将其绑定到GUI中。
然后我对Workout进行了扩展:
extension Workout{
public override func value(forKey key: String) -> Any? {
if key == "rpeTSS"{
return (100/49)*rpe*rpe*Double(seconds)/3600
}else{return super.value(forKey: key)}
}
}
我会说实话,这感觉不对。无论如何它(有点)有效。我现在得到rpeTSS的正确值,它出现在我的gui中。但是,如果我对rpe和/或秒进行更改,则GUI不会更新。
我猜测上面的方法有点乱,因此绕过各种消息传递,让GUI更新。
在核心数据中添加派生属性的正确方法是什么?我试图以一种方式实现这一点,这意味着如果我向我的数据模型添加任何内容,我就不必重新编写派生属性的代码。
答案 0 :(得分:2)
仍然不确定这是正确的方法,但确实解决了问题。但是如果有正确的话,我会感兴趣的。做我想做的事。
我设法通过覆盖扩展程序中的setValue(:forKey)方法来更新所有内容:
extension Workout{
public override func value(forKey key: String) -> Any? {
if key == "rpeTSS"{
if rpeTSS == 0{
self.rpeTSS = (100/49)*rpe*rpe*Double(seconds)/3600
}
return rpeTSS
}
return super.value(forKey: key)
}
public override func setValue(_ value: Any?, forKey key: String) {
super.setValue(value, forKey: key)
if (key == "rpe") || (key == "seconds") {
self.rpeTSS = calculateRPETSS()
}
}
func calculateRPETSS() -> Double{
return (100/49)*rpe*rpe*Double(seconds)/3600
}
}
答案 1 :(得分:1)
不确定这是不是你的意思,但是......
我有一个名为Person
的实体类。这是我的两个班级:
人+ CoreDataProperties.swift:
extension Person {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Total> {
return NSFetchRequest<Person>(entityName: "Person")
}
@NSManaged public var name: String?
@NSManaged public var age: Int
}
人+ CoreDataClass.swift:
@objc(Person)
public class Total: NSManagedObject {
}
这些是由Xcode生成的。然后在我的ViewController
中,当我想使用这个类时,我使用:
var curPerson: Person?
let personEntity = NSEntityDescription.entity(forEntityName: "Person", in: Singleton.s.context)!
Singleton.s.people = try Singleton.s.context.fetch(Person.fetchRequest())
// find the current person
for p in Singleton.s.people {
if p.name == curName { // got it
curPerson = p
break
}
}
现在我有一个Person
对象要操纵。要使用新对象:
let newPerson = Person(entity: personEntity, insertInto: Singleton.s.context)
为了确保保存我的更改,我使用:
(UIApplication.shared.delegate as! AppDelegate).saveContext()
答案 2 :(得分:1)
我想出的最终解决方案看起来和感觉都是正确的。它需要重写keyPathsForValuesAffectingValue(forKey :),如下所示:
extension Workout{
@objc dynamic var rpeTSS: Double{
return (100/49)*rpe*rpe*Double(seconds)/3600
}
override public class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>{
let keyPaths = super.keyPathsForValuesAffectingValue(forKey: key)
switch key {
case "rpeTSS":
return keyPaths.union(Set(["seconds","rpe"]))
default:
return keyPaths
}
}