ios - 需要有关核心数据关系概念的帮助,不要求任何代码

标签 ios core-data

我目前正在研究核心数据和新手,从地址簿中获取复合名称和联系电话。我现在可以使用 KVC 和子类化 NSManagedObject 以一对一和对多关系保存数据。但是还有一些概念我不太清楚。

enter image description here

在普通的数据库中,我们以主键和外键的方式保存数据。 ContactName 表中的 ID、compositeName 字段和 ContactNumber 表中的 ID、number、type 字段。可以在两个表 ID 字段上轻松创建关系。

在核心数据中,它是这样使用 KVC 完成的:

1.        NSManagedObject *contactNameEntity = [NSEntityDescription insertNewObjectForEntityForName:@"ContactName" inManagedObjectContext:self.managedObjectContext];

2.                [contactNameEntity setValue:@"TheName" forKey:@"compositeName"]

3.                NSMutableSet *relationAsSet = [contactNameEntity mutableSetValueForKey:@"contactNameRelation"];

    //fetching multi values like contact mobile, iPhone, home, work, other numbers and iterating them
4.                ABMutableMultiValueRef multiValues = ABRecordCopyValue(ref, kABPersonPhoneProperty);
5.                        CFArrayRef mVArray = ABMultiValueCopyArrayOfAllValues(multiValues);
6.                        for(int i=0; i<CFArrayGetCount(mVArray); i++) {
7.                            NSManagedObject *contactNumberEntity = [NSEntityDescription insertNewObjectForEntityForName:@"ContactNumber" inManagedObjectContext:self.managedObjectContext];
8.                            [contactNumberEntity setValue:(__bridge NSString*)CFArrayGetValueAtIndex(mVArray, i) forKey:@"number"];
9.                            [contactNumberEntity setValue:(__bridge id)(ABMultiValueCopyLabelAtIndex(multiValues, i)) forKey:@"type"];
10.                            [relationAsSet addObject:contactNumberEntity];
                        }

11.        [contactNameEntity setValue:relationAsSet forKey:@"contactNameRelation"];

现在使用实体子类方法#1:

1.        ContactName *contactNameEntity = [NSEntityDescription insertNewObjectForEntityForName:@"ContactName" inManagedObjectContext:self.managedObjectContext];
2.                [contactNameEntity setCompositeName:(__bridge id)(compositeName)];

3.    for(int i=0; i<CFArrayGetCount(mVArray); i++) {
4.                ContactNumber *contactNumberEntity = [NSEntityDescription 
5. insertNewObjectForEntityForName:@"ContactNumber" inManagedObjectContext:self.managedObjectContext];
6.                [contactNumberEntity setNumber:(__bridge NSString*)CFArrayGetValueAtIndex(mVArray, i)];
7.                [contactNumberEntity setType:(__bridge id)(ABMultiValueCopyLabelAtIndex(multiValues, i))];
8.                [contactNameEntity addContactNameRelationObject:contactNumberEntity];
            }

现在有了类似于 KVC 方法 #2 的实体子类:

1.    ContactName *contactNameEntity = [NSEntityDescription insertNewObjectForEntityForName:@"ContactName" inManagedObjectContext:self.managedObjectContext];
2.             [contactNameEntity setCompositeName:(__bridge id)(compositeName)];

3.    NSSet *set = [contactNameEntity contactNameRelation];
4.            NSMutableSet *mSet = [NSMutableSet setWithSet:set];
5.            set = nil;

6.    for(int i=0; i<CFArrayGetCount(mVArray); i++) {
7.                ContactNumber *contactNumberEntity = [NSEntityDescription 
8. insertNewObjectForEntityForName:@"ContactNumber" inManagedObjectContext:self.managedObjectContext];
9.                [contactNumberEntity setNumber:(__bridge NSString*)CFArrayGetValueAtIndex(mVArray, i)];
10.                [contactNumberEntity setType:(__bridge id)(ABMultiValueCopyLabelAtIndex(multiValues, i))];
11.                [mSet addObject:contactNumberEntity];
            }

12.    [contactNameEntity addContactNameRelation:mSet];

问题:

  1. KVC方法第3行,为什么无法创建普通的NSSet?

  2. 为什么关系以 NSSet 的形式存在,虽然在正常的 DB 关系中只是一件简单的事情,但在核心数据中似乎很复杂。

  3. 我是否正确使用了子类生成的方法,或者我是否以标准方式使用了子类生成的方法? (要求验证我的概念)。

  4. 为什么方法 #1 和方法 #2 不同?两者都在使用子类。

  5. @property (nonatomic, retain) NSSet *contactNameRelation;NSMutableSet *relationAsSet = [contactNameEntity mutableSetValueForKey:@"contactNameRelation"]; 返回相同的对象/值?

*。请避免任何愚蠢的错误。

*。请告诉我我问的问题不清楚。

编辑 1

ContactName实体xcode生成的子类.h文件:

@property (nonatomic, retain) NSString * number;
@property (nonatomic, retain) NSSet *contactNumbers;
@end

@interface ContactName (CoreDataGeneratedAccessors)

- (void)addContactNumbersObject:(ContactNumber *)value;
- (void)removeContactNumbersObject:(ContactNumber *)value;
- (void)addContactNumbers:(NSSet *)values;
- (void)removeContactNumbers:(NSSet *)values;

这是 .m 文件:

@implementation ContactName

@dynamic compositeName;
@dynamic contactNumbers;

@end

我想知道如何正确使用这些方法,这就是为什么方法 1 和方法 2 是我上面基于此子类发布的两种不同方法的原因。什么是正确的,什么是不正确的,请帮助我。

编辑2

这是我在记录 relationAsSet 时得到的结果

$0 = 0x0854c1c0 Relationship 'contactNameRelation' on managed object (0x835bae0) <ContactName: 0x835bae0> (entity: ContactName; id: 0x835ba80 <x-coredata:///ContactName/t66752D00-F08B-40DF-AEED-ABCACEA254652> ; data: {
    compositeName = myname;
    contactNameRelation =     (
    );
}) with objects {(
)}

还有这个

$0 = 0x0821b460 Relationship 'contactNameRelation' on managed object (0x823fe50) <ContactName: 0x823fe50> (entity: ContactName; id: 0x823fea0 <x-coredata:///ContactName/t3CED08C3-94E0-4B43-93F0-96DE2D2A24922> ; data: {
    compositeName = myname;
    contactNameRelation =     (
        "0x821be40 <x-coredata:///ContactNumber/t3CED08C3-94E0-4B43-93F0-96DE2D2A24923>"
    );
}) with objects {(
    <ContactNumber: 0x8241ab0> (entity: ContactNumber; id: 0x821be40 <x-coredata:///ContactNumber/t3CED08C3-94E0-4B43-93F0-96DE2D2A24923> ; data: {
    contactNumberRelation = "0x823fea0 <x-coredata:///ContactName/t3CED08C3-94E0-4B43-93F0-96DE2D2A24922>";
    number = 123;
    type = iphone;
})
)}

最佳答案

正如@svena 已经说过的,您的关系名称有点“非常规”(而且您似乎已经在添加的代码中部分更改了它们)。所以我将采用以下模型和关系名称:

Core Data Model

一对多关系的值是一个NSSet。例如

ContactName *aContact = ...;
NSSet *relatedNumbers = aContact.contactNumbers;
// or equivalently, using KVC:
relatedNumbers = [aContact valueForKey:@"contactNumbers"];
for (ContactNumber *contactNumber in relatedNumbers) {
    NSLog(@"%@", contactNumber.number);
}

因此您使用关系的值(在本例中为 NSSet)来遍历对象 图并找到相关对象。但是你不能修改这个集合(它是不可变的)。

然后你有关于

的问题
NSMutableSet *mutableRelatedNumbers = [aContact mutableSetValueForKey:@"contactNumbers"];

这是一件很特别的事情。它是一个可变集,“绑定(bind)”到 aContact 对象。这意味着如果你修改这个集合(添加或删除一些东西)然后你有效地修改 aContact 对象的 contactNumbers 关系。

所以

ContactName *aContact = ...;
ContactNumber *aContactNumber1 = ...;
ContactNumber *aContactNumber2 = ...;

// (A)
NSMutableSet *mutableRelatedNumbers = [aContact mutableSetValueForKey:@"contactNumbers"];
[mutableRelatedNumbers addObject:aContactNumber1];
[mutableRelatedNumbers addObject:aContactNumber2];

(这是您的第一个代码块的更正版本)是执行此操作的复杂方法

// (B)
[aContact addContactNumbersObject:aContactNumber1];
[aContact addContactNumbersObject:aContactNumber2];

(这是您的方法#1)。另一种等价的方法是(因为反比关系)

// (C)
aContactNumber1.contactName = aContact;
aContactNumber2.contactName = aContact;

// (D)
NSMutableSet *mset = [NSMutableSet set];
[mset addObject:aContactNumber1];
[mset addObject:aContactNumber2];
[aContact addContactNumbers:mset];

类似于 (B),是您的方法 #2 的更正版本。

这些都是将对象添加到关系中的有效方法,但 (C) 最容易使用,其次是 (B)。 (A) 和 (D) 很少使用。 (C) 的另一个优点是更好的类型检查。

所以即使我没有直接回答问题,我也希望这有助于澄清问题!

关于ios - 需要有关核心数据关系概念的帮助,不要求任何代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15810203/

相关文章:

ios - 在 IOS 8.3 中可以找到 Couchbase lite 位置的位置是什么?

ios - 第一个函数执行完成后如何调用第二个函数?

ios - didRegisterForRemoteNotificationsWithDeviceToken 在 swift 5 中不起作用

ios - 获取核心数据最新 -id 并为新插入提供 -(+1)

iphone - JSON 到持久数据存储(CoreData 等)

ios - Xcode 6.3.2 - iOS - 不明确的 UIImageView

ios - 如何清除 WKWebView 中的历史记录?

ios - 为什么在旧设备上首次打开时将预填充的数据库加载到核心数据时应用程序崩溃?

ios - NSPredicate过滤关系

objective-c - Core Data 中的自定义初始化程序和只读属性