Добавление отношений в NSManagedObjectModel к программно созданному NSEntityDescription
Когда вы пишете статическую библиотеку, которая использует CoreData, возникает большой беспорядок, включая обычный файл.xdatamodeld в проект, потому что вы просто не можете просто связать его скомпилированную версию (.momd) с вашим двоичным файлом, поэтому лучше создать целое NSManagedObjectModel
в коде так:
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];
И все просто идеально....
Но! Подождите, если у меня есть более одного объекта в моем NSManagedObjectModel
и они связаны (со многими, инвертированными и т. д.), как в мире я собираю их соединить в коде, как в примере выше, без того приятного редактора Xcode, где вы создаете отношения несколькими щелчками мыши?
пример
Представьте себе, у нас есть класс MyCustomElement, который почти такой же, как в MyCustomEntry из приведенного выше кода. Теперь вот их интерфейсы, как они выглядели бы, если бы я использовал генерацию Xcode для сущностей:
@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
Какое NSRelationshipDescription мне нужно создать для них и как его инициировать?
1 ответ
Отношения описываются NSRelationshipDescription
объекты. Следующий код создает два описания сущностей для "MyCustomEntry", "MyCustomElement" со связями
entries
(MyCustomElement -> MyCustomEntry, to-many),element
(MyCustomEntry -> MyCustomElement, to-one), обратныйentries
,
Обе сущности имеют только строковый атрибут "идентификатор" (для сохранения некоторых строк кода).
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 (теперь обновлен для 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]
Я протестировал этот код, и он, кажется, работает, поэтому я надеюсь, что он будет вам полезен.