objective-c - 将 NSManagedObjectModel 中的关系添加到以编程方式创建的 NSEntityDescription

标签 objective-c cocoa core-data nsmanagedobject 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 以及如何初始化它?

最佳答案

关系由 NSRelationshipDescription 对象描述。以下代码为“MyCustomEntry”、“MyCustomElement”创建两个具有关系的实体描述

  • 条目(MyCustomElement --> MyCustomEntry,对多),
  • element(MyCustomEntry --> MyCustomElement,一对一),entries 的倒数。

两个实体都只有一个字符串属性“identifier”(为了节省一些代码行)。

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]

我已经测试了这段代码,它似乎可以工作,所以我希望它对你有用。

关于objective-c - 将 NSManagedObjectModel 中的关系添加到以编程方式创建的 NSEntityDescription,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13743242/

相关文章:

ios - UIWebView 和 UITableView 同时滚动

objective-c - 取消选择 RowAtIndexPath : failing in iOS5

iphone - 我如何将指南针指向我的目的地?

xml - Cocoa XML 阅读器应用程序

swift - 核心数据从日志中单独显示属性

ios - 在 Objective-C 中创建仅对子类可见的属性

objective-c - 如何默认启用第三方服务?

macos - Mac OS X/Cocoa : create "docked" sidebar that reduces maximizable area, 就像 Dock

ios - 基于一对多关系的谓词

iphone - 具有 AND 和 OR 问题的 NSPredicate