1

I would like to add attributes programmatically to an entity during runtime of my app.

Is this something you would recommend doing or can this lead to issues?

How would I need to combine NSAttributeDescription and NSEntityDescription? I am familiar with creating models using Xcode, but did not do it using NSEntityDescription yet.

AlexR
  • 5,514
  • 9
  • 75
  • 130
  • This is an interesting request. Have you considered having a mutable dictionary for your objects instead? – Rey Gonzales Mar 25 '13 at 21:30
  • Rey, I don't know if that would work. I have a large time series sample (stored in Core Data as date and value type a) to which I would like to add additional value types b and c. – AlexR Mar 25 '13 at 21:34
  • 1
    Hm. If I were you I'd add a transformable data type to my entity, extend the NSMutableDictionary to have multiple values for one key (the date), and then store my values in there – Rey Gonzales Mar 25 '13 at 21:36
  • This sounds very interesting, Rey! I will definitively look into this. However, I cannot perform databased based calculations as easily as I could do it using standard attributes. – AlexR Mar 25 '13 at 21:38
  • 1
    If you simply want to extend an existing model/object graph, this sounds like a case for a new model version, and lightweight model migration. You can add new attributes and Core Data will update the datastore for you. Then you can programmatically update values b and c. – Hal Mueller Mar 25 '13 at 21:40

5 Answers5

3

It's theoretically possible, but doesn't appear very practical.

You can modify the NSManagedObjectModel programmatically, as well as NSEntityDescription. Note that -setEntities: (NSManagedObjectModel) and -setProperties: (NSEntityDescription) both trigger exceptions if you modify a model that has been instantiated. So you can't modify your existing model's structure. You'd have to create a new one and copy all of your data from the old Core Data stack to the new one based on your new model..

Using NSMutableDictionary is a much saner approach.

Hal Mueller
  • 7,019
  • 2
  • 24
  • 42
  • 1
    How about creating a new 1:n relationship between dates and n values? – AlexR Mar 25 '13 at 21:44
  • That sounds sane as well. With proper naming I'm sure it'd be even more clear than an NSMutableDictionary as a transformable type. – Rey Gonzales Mar 25 '13 at 21:46
  • 1
    It's not clear to me at this point what you're really trying to do with your object graph. If you know, at design/compile time, that you will have observation date, Type A records, Type B records, and Type C records, then you should build the model accordingly, with 4 separate Entities (date/A/B/C), and you'll have a very clear, clean design. If you really need runtime variability (meaning that you don't know until runtime what the data looks like), you'll have to resort to NSMutableDictionary/transformable type shenanigans. – Hal Mueller Mar 25 '13 at 21:51
2

This is an article talking about this in great detail. Hope it helps.

Matt
  • 2,391
  • 2
  • 17
  • 18
1

I would not do this. If the store becomes incompatible with your model it will just crash. Is this risk really worth the benefit you are trying to create?

I have found that it makes sense to create more (even many more) attributes upfront just "to be on the safe side". The overhead of unused attributes is really minimal, but you get the flexibility of easily adding information to your objects "on the fly".

As pointed out in the comments, one good way to implement that is using a separate entity for attributes and adding them as to-many relationships.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • If I would separate the date and the values in separate entities in a 1:n relationship in order to have n values for 1 date, how would be the fetch performance affected compared to your solution of storing unused attributes? Thank you! – AlexR Mar 25 '13 at 21:43
  • Using 1:n relationship will make for a much cleaner design. Alex, you said above that you want to add 2 value types. If you really mean "n" instead of 2, using separate entities is the way to go. – Hal Mueller Mar 25 '13 at 21:49
  • Very good observations! Indeed, I have a live commercial project where I have a to-many attribute called `attributes` to give me this flexibility. It is working very well. – Mundi Mar 25 '13 at 22:19
0

I just used nearly the same technique here: EPPZQueuedObject.h

Although, I think mutate the entity architecture during runtime could lead to incompatiblity issues (an exception actually), when the stored SQLite data won't fit for your initial entities at startup.

So this generic object EPPZQueuedObject is an object of two attributes at all, so I had no intention to use a separate model file only for this purpose. But this structure is not mutating during runtime.

@implementation EPPZQueuedObject


@dynamic creationDate;
@dynamic archivedObject;


+(NSEntityDescription*)entityDescription
{
    //Describe EPPZQueuedObject.
    NSEntityDescription *entityDescription = [NSEntityDescription new];
    entityDescription.name = EPPZQueuedObjectEntityName;
    entityDescription.managedObjectClassName = NSStringFromClass(self);

    //Describe creationDate.
    NSAttributeDescription *creationDateDescription = [NSAttributeDescription new];
    creationDateDescription.name = @"creationDate";
    creationDateDescription.attributeType = NSDateAttributeType;
    creationDateDescription.attributeValueClassName = @"NSDate";
    creationDateDescription.defaultValue = nil;    

    //Describe archivedObject.    
    NSAttributeDescription *archivedObjectDescription = [NSAttributeDescription new];
    archivedObjectDescription.name = @"archivedObject";    
    archivedObjectDescription.attributeType = NSBinaryDataAttributeType;
    archivedObjectDescription.attributeValueClassName = @"NSData";
    archivedObjectDescription.defaultValue = nil;

    //Add attributes.
    entityDescription.properties = @[ creationDateDescription, archivedObjectDescription ];

    //Voila.
    return entityDescription;
}


@end

More details in the corresponding article: http://eppz.eu/blog/simple-core-data-sample/

Geri Borbás
  • 15,810
  • 18
  • 109
  • 172
0

I'm working on something similar and I'm thinking about creating a new core data class called "Properties", so I can set my core data objects to have a "relationship to many Properties". Each Property would have core data string-type attributes: "attribute", "type" and "value".

I think that should give enough flexibility to add properties to a core data object in the fly. If I happen to implement this, I will post it here

Lucas Chwe
  • 2,578
  • 27
  • 17