2017-10-05 190 views
0

创建一个计算的属性我的影片迷上了一个Storyboard GUI(Xcode中9和SWIFT 4)核心数据模型现在我想添加这是由两部分衍生的特性。我有一个名为Workout的实体,它的两个属性“rpe”和“seconds”被组合起来创建一个新属性“rpeTSS”。我在我的核心数据模型中声明了“repTSS”作为属性。我已将其设置为瞬态。在核心数据

我已经使用编辑菜单下的“让子类NSManagedObject ...”选项尝试,但,这似乎产生具有错误的文件。我尝试了生成的Workout类的子类,但无法弄清楚如何将它绑定到GUI中。

我再发的扩展,锻炼:

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

您可以创建实体类的对象并在其中设置属性?然后,无论何时您更改rpe或秒,都会更新rpeTSS属性。 – CodeNinja

+0

不确定你的意思。实体类是在XCode中自动生成的。我尝试了继承它,但遇到了两个问题 - 1.如何使ManagedObject成为我的子类的一个实例并绑定到GUI中的子类;和2.我不断收到错误,我的计算属性不符合关键值。 –

回答

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()

+0

谢谢。那给了我一些想法。在我的情况下,我使用GUI和阵列控制器中的绑定来创建我的对象。所以目前我没有实例化我的实体的实例。我试图保持这种方式 –

+0

啊,陷入困境。好吧,祝你好运! – CodeNinja

1

仍然不知道这是做正确的方式,但它按照要求解决问题。不过,如果有一种“正确”的方式来做我想做的事,我会感兴趣。

我设法得到它全部重写的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 
} 

}

0

我想出了外观和感觉正确的最终解决方案。它需要覆盖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 
     } 
}