I have a core data model that's hooked up to a Storyboard GUI.(Xcode 9 and SWIFT 4) I now want to add a property which is derived from two others. I have an Entity called Workout and two of it's properties "rpe" and "seconds" are combined to create a new property "rpeTSS". I have declared "repTSS" as an attribute in my core data model. I've set it to transient.
I have tried using the "make NSManagedObject subclass..." option under the Editor menu but this seemed to produce files with errors. I tried subclassing the generated Workout class but couldn't figure out how to bind that in to the GUI.
I then made an extension to 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)}
}
}
I'll be honest this doesn't 'feel' right. Anyway it (kind of) works. I do now get the correct value for rpeTSS and it shows up in my gui. However if I make changes to rpe and/or seconds the GUI doesn't update.
I'm guessing the method above is a bit of a hack and thus circumvents various messaging that gets the GUI to update.
What is the correct way to add derived properties within core data? I'm trying to achieve this in a way that means if I add anything to my data model I don't have to go re-writing of the code for the derived properties.
Still not sure this is the right way to do it but it does solve the question as asked. However I would be interested if there is a 'right' way to do what I'm trying.
I managed to get it all to update by overriding the setValue(: forKey) method in my extension:
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
}
}
Not sure if this is what you mean, but...
I have an Entity class called Person
. Here are my two classes:
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
}
Person+CoreDataClass.swift:
@objc(Person)
public class Total: NSManagedObject {
}
These were generated by Xcode. And then in my ViewController
when I want to use this class I use:
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
}
}
Now I have a Person
object to manipulate. To make a new object I use:
let newPerson = Person(entity: personEntity, insertInto: Singleton.s.context)
And to make sure my changes are saved I use:
(UIApplication.shared.delegate as! AppDelegate).saveContext()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With