保存一对多关系CoreData

Posted

技术标签:

【中文标题】保存一对多关系CoreData【英文标题】:Saving one-to-many relationship CoreData 【发布时间】:2013-02-04 21:45:51 【问题描述】:

我在 CoreData 中设置的关系有问题。它是一对多的,一个客户可以有多个联系人,这些联系人来自通讯录。

我的模型是这样的:

Customer <---->> Contact
Contact  <-----> Customer

Contact.h

@class Customer;

@interface Contact : NSManagedObject

@property (nonatomic, retain) id addressBookId;
@property (nonatomic, retain) Customer *customer;

@end

客户.h

@class Contact;

@interface Customer : NSManagedObject

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSSet *contact;

@end

@interface Customer (CoreDataGeneratedAccessors)

- (void)addContactObject:(Contact *)value;
- (void)removeContactObject:(Contact *)value;
- (void)addContact:(NSSet *)values;
- (void)removeContact:(NSSet *)values;

@end

并尝试保存:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
Customer *customer = (Customer *)[NSEntityDescription insertNewObjectForEntityForName:@"Customer" inManagedObjectContext:context];

[customer setValue:name forKey:@"name"];

for (id contact in contacts) 
    ABRecordRef ref = (__bridge ABRecordRef)(contact);
    Contact *contact = [NSEntityDescription insertNewObjectForEntityForName:@"Contact" inManagedObjectContext:context];

    [contact setValue:(__bridge id)(ref) forKey:@"addressBookId"];
    [customer addContactObject:contact];


NSError *error;

if ([context save:&error])  // <----------- ERROR
    // ...

使用我的代码,我有这个错误:

-[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x9c840c0
*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x9c840c0'

任何建议将不胜感激。

【问题讨论】:

如何在您的数据模型中配置addressBookId?您使用的是什么核心数据类型? Contact.m 是否有此属性的自定义设置器代码? 一种可能性是,您设置的 value 属性类型与数据模型上声明的属性类型不同 @TomHarrington Contact.m 没有任何自定义代码。而数据模型中的addressBookIdTransformable 我不确定您是否可以将 ABRecordRef 桥接到这样的对象。 AddressBook 中没有表示联系人的对象。我建议创建自己的对象,或者简单地将 ABRecordRef id 保存为 CoreData 中的数字,并在需要时从 AB 读取它。保存到 CoreData 中的任何对象都需要支持编码,而且我不认为那个桥在工作。 【参考方案1】:

问题在于addressBookId 被定义为Contact 实体上的可转换属性(正如您在评论中提到的)。但是(正如您在评论中提到的那样)您没有任何自定义代码来实际将 ABRecordRef 转换为 Core Data 知道如何存储的东西。在没有自定义转换器的情况下,Core Data 将尝试通过在值上调用 encodeWithCoder: 来转换值。但是ABRecordRef 不符合NSCoding,所以这会失败并且您的应用会崩溃。

如果您想将ABRecordRef 存储在Core Data 中,您需要创建一个NSValueTransformer 子类并在您的数据模型中配置它。您的转换器需要将 ABRecordRef 转换为 Core Data 知道的类型之一。我还没有充分使用地址簿 API 来提供有关此细节的建议,但 Apple 文档 NSValueTransformer 非常好。

它是一对多关系这一事实是无关紧要的;问题是ABRecordRef 不能在没有经过一些转换的情况下进入您的数据存储。

【讨论】:

以上是关于保存一对多关系CoreData的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:一对多关系 - 没有保存细节

Core Data 使用多个上下文中的新对象从后台线程订购一对多关系保存

CoreData 一对多关系

Swift 2.1 Core Data - 保存具有一对多关系的数据,但如果已经存在则不要添加异构数据

CoreData 一对多关系问题

CoreData - 一对多关系