Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use derived attributes in Core Data

I'm working with Core Data. I have a field called date that could contain a date or nil.

I want to make a second field called sortDate that will use the date value from the date field if there is one. If the date field is nil, I want to return the current date. I need this to be a core data attribute (not a computed property) because I need to sort fetched records based on this value.

I think the way to do this is with derived attributes but I can't find any information on how to use them. I selected the checkbox called "Derived". This shows the "Derivation expression" field, but I have no idea what to enter here. There is no link to documentation on the Xcode UI.

Despite the comment below, I cannot locate any documentation for this feature. I've searched the documentation many times and can't find a single word from Apple about this other than this WWDC session where they mention documentation but do not link to it to say how to find it.

I'm not the only one failing to find this: Documentation on core data derived attributes

like image 322
radicalappdev Avatar asked Dec 09 '25 00:12

radicalappdev


2 Answers

One solution I've used in the past and has always worked for me is to add it as a property in the model and then update it programmatically on willSave.

For example:

@objc(MyCoreDataModelObject)
class MyCoreDataModelObject: NSManagedObject {
    @NSManaged var date: Date?

    override func willSave() {
        setPrimitiveValue(
            date.map { ISO8601DateFormatter().string(from: $0) },
            forKey: "sortDate"
        )
    }
}

If you already have a version of your model with date then you also have to do separate code to generate the current sortDate for those.

like image 153
fbernardo Avatar answered Dec 11 '25 21:12

fbernardo


Expanding on the link @radicalappdev posted as a comment:

So you can find the documentation here now.

Short answer is that it's super disappointing. You scan either specify an attribute on the current entity or on the target of a to-one relationship using the forms

attrname
relationship.attrname

You can precede the above expressions with the operators canonical:, uppercase:, and lowercase:, e.g., lowercase:attrname.

Or you can count the objects in a to-many relationship or sum on of their attributes using the syntax

relationship.@count
relationship.attribute.@sum

That appears to be fucking all of it. Yes, you can't even take the max as far as I can tell from other answers here. It feels like someone built the framework for a decent feature and then left the company and it got forgotten.

like image 39
Peter Gerdes Avatar answered Dec 11 '25 23:12

Peter Gerdes