Adding relationships in NSManagedObjectModel to programmatically created NSEntityDescription

ぐ巨炮叔叔 提交于 2019-11-27 16:28:32

问题


When you write a static library which uses CoreData there's a big mess including a normal .xdatamodeld file into the project because you simply cannot just link its compiled version (.momd) into your binary, so it's better to create the whole NSManagedObjectModel in the code like this:

NSAttributeDescription *dateAttribute = NSAttributeDescription.new;

dateAttribute.name = @"timestamp";
dateAttribute.attributeType = NSDoubleAttributeType;
dateAttribute.optional = NO;
dateAttribute.indexed = YES;

NSAttributeDescription *payloadAttribute = NSAttributeDescription.new;

payloadAttribute.name = @"payload";
payloadAttribute.attributeType = NSBinaryDataAttributeType;
payloadAttribute.optional = NO;
payloadAttribute.indexed = NO;

NSEntityDescription *entry = NSEntityDescription.new;

entry.name = entry.managedObjectClassName = NSStringFromClass(MyCustomEntry.class);
entry.properties = @[dateAttribute, payloadAttribute];

NSManagedObjectModel *mom = NSManagedObjectModel.new;

mom.entities = @[entry];

And everything is just perfect....

But! Wait, if I have more than one entity in my NSManagedObjectModel and they are related (to-many, inversed, and so on), how in the world I gonna connect them in the code, like in example above, without that nice Xcode editor, where you make relationships with several mouse clicks?

Example

Imagine, we have a class MyCustomElement, which is almost the same as in MyCustomEntry from the code above. Now, here're their interfaces how they would appear if I used Xcode generation for entities:

@interface MyCustomEntry : NSManagedObject

@property (nonatomic, retain) NSNumber *timestamp;
@property (nonatomic, retain) NSData *payload;
@property (nonatomic, retain) MyCustomElement *element;

@end

@interface MyCustomElement : NSManagedObject

@property (nonatomic, retain) NSNumber * timestamp;
@property (nonatomic, retain) NSString * identifier;
@property (nonatomic, retain) NSSet *entries;

@end

@interface MyCustomElement (CoreDataGeneratedAccessors)

- (void)addEntriesObject:(MyCustomEntry *)value;
- (void)removeEntriesObject:(MyCustomEntry *)value;
- (void)addEntries:(NSSet *)values;
- (void)removeEntries:(NSSet *)values;

@end

What NSRelationshipDescription I need to create for them and how to init it?


回答1:


Relationships are described by NSRelationshipDescription objects. The following code creates two entity descriptions for "MyCustomEntry", "MyCustomElement" with relationships

  • entries (MyCustomElement --> MyCustomEntry, to-many),
  • element (MyCustomEntry --> MyCustomElement, to-one), inverse of entries.

Both entities have only a string attribute "identifier" (to save some lines of code).

Objective-c:

NSEntityDescription *entry = [[NSEntityDescription alloc] init];
[entry setName:@"MyCustomEntry"];
[entry setManagedObjectClassName:@"MyCustomEntry"];

NSAttributeDescription *entryIdAttribute = [[NSAttributeDescription alloc] init];
entryIdAttribute.name = @"identifier";
entryIdAttribute.attributeType = NSStringAttributeType;

NSEntityDescription *element = [[NSEntityDescription alloc] init];
[element setName:@"MyCustomElement"];
[element setManagedObjectClassName:@"MyCustomElement"];

NSAttributeDescription *elementIdAttribute = [[NSAttributeDescription alloc] init];
elementIdAttribute.name = @"identifier";
elementIdAttribute.attributeType = NSStringAttributeType;

// To-many relationship from "Element" to "Entry":
NSRelationshipDescription *entriesRelation = [[NSRelationshipDescription alloc] init];

// To-one relationship from "Entry" to "Element":
NSRelationshipDescription *elementRelation = [[NSRelationshipDescription alloc] init];

[entriesRelation setName:@"entries"];
[entriesRelation setDestinationEntity:entry];
[entriesRelation setMinCount:0];
[entriesRelation setMaxCount:0]; // max = 0 for to-many relationship
[entriesRelation setDeleteRule:NSCascadeDeleteRule];
[entriesRelation setInverseRelationship:elementRelation];

[elementRelation setName:@"element"];
[elementRelation setDestinationEntity:element];
[elementRelation setMinCount:0];
[elementRelation setMaxCount:1]; // max = 1 for to-one relationship
[elementRelation setDeleteRule:NSNullifyDeleteRule];
[elementRelation setInverseRelationship:entriesRelation];

[entry setProperties:@[entryIdAttribute, elementRelation]];
[element setProperties:@[elementIdAttribute, entriesRelation]];

NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] init];
[mom setEntities:@[entry, element]];

Swift (now updated for Swift 3/4):

let entry = NSEntityDescription ()
entry.name = "MyCustomEntry"
entry.managedObjectClassName = "MyCustomEntry"

let entryIdAttribute = NSAttributeDescription()
entryIdAttribute.name = "identifier";
entryIdAttribute.attributeType = .stringAttributeType;

let element = NSEntityDescription()
element.name = "MyCustomElement"
element.managedObjectClassName = "MyCustomElement"

let elementIdAttribute =  NSAttributeDescription()
elementIdAttribute.name = "identifier"
elementIdAttribute.attributeType = .stringAttributeType

// To-many relationship from "Element" to "Entry":
let entriesRelation = NSRelationshipDescription()

// To-one relationship from "Entry" to "Element":
let elementRelation = NSRelationshipDescription ()

entriesRelation.name = "entries"
entriesRelation.destinationEntity = entry
entriesRelation.minCount = 0
entriesRelation.maxCount = 0  // max = 0 for to-many relationship
entriesRelation.deleteRule = .cascadeDeleteRule
entriesRelation.inverseRelationship = elementRelation

elementRelation.name = "element"
elementRelation.destinationEntity = element
elementRelation.minCount = 0
elementRelation.maxCount = 1 // max = 1 for to-one relationship
elementRelation.deleteRule = .nullifyDeleteRule
elementRelation.inverseRelationship = entriesRelation

entry.properties = [entryIdAttribute, elementRelation]
element.properties = [elementIdAttribute, entriesRelation]

let mom = NSManagedObjectModel()
mom.entities = [entry, element]

I have tested this code and it seems to work, so I hope that it will be useful to you.



来源:https://stackoverflow.com/questions/13743242/adding-relationships-in-nsmanagedobjectmodel-to-programmatically-created-nsentit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!