Core Data iPhone中的主键行为

时间:2009-11-10 19:24:50

标签: iphone objective-c cocoa core-data primary-key

我正在创建一个应用程序来解析来自xml的提要并使用Core Data存储它们。 我目前处理的问题是重复的条目。我正在解析的每个feed都包含一个唯一的id,这是我作为int在模型中得到的东西。现在我需要的是告诉核心数据存储该实体,如果已存在具有相同ID的另一个实体。

举个例子,假设我的模型具有以下属性:

Story.id (int) - primary key
Story.title (NSString)
Story.date (NSDate)

实施该方法的最佳方法是什么?

我的方法是保留数据库中所有可用ID的记录(数组),并在插入任何内容之前,检查它是否存在。这可能适用于我的应用程序的大小,但我觉得这不是正确的方法。

2 个答案:

答案 0 :(得分:8)

我看到两种方法。在我看来,后者(你提出的方法)是更好的解决方案。

我将id更改为primaryKey,因为我不认为在Object-C中使用id作为变量或方法名称是个好主意,因为它是一个关键字。我可能会工作,我从来没有真正尝试过。我还假设primaryKey是一个NSNumber,因为这将是如何存储在Core Data中的。

方法一每次都会对上下文执行一次获取请求:

for (id data in someSetOfDataToImport) {
    NSFetchRequest * request = [[NSFetchRequest alloc] init];

    [request setEntity:[NSEntityDescription entityForName:@"Story" inManagedObjectContext:context]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"primaryKey = %d", primaryKey]];
    NSUInteger count = [context countForFetchRequest:request error:nil];
    [request release];

    if (count > 0)
        continue;

    // Insert data in Managed Object Context
}

方法二做你提出的建议,将密钥缓存在一个数组中并检查它而不是去源:

NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Story" inManagedObjectContext:context]];
NSArray * allStories = [context countForFetchRequest:request error:nil];
[request release];

NSMutableArray * allPrimaryKeys = [[allStories valueForKeyPath:@"@distinctUnionOfObjects.primaryKey"] mutableCopy];

for (id data in someSetOfDataToImport) {
    if ([allPrimaryKeys containsObject:data.primaryKey])
        continue;

    [allPrimaryKeys addObject:data.primaryKey];

    // Insert data in Managed Object Context
}

[allPrimaryKeys release];

答案 1 :(得分:3)

我会警告你不要过早优化。它是所有编程邪恶的根源,浪费时间。

坦率地说,在iPhone上,你几乎不可能得到如此巨大的物体图,你开始注意到它会让事情陷入困境。我无法想象你每秒都在处理数百个独特的xml提要。

除非您同时处理数十万个主键,否则谓词方法将花费大量时间和资源,同时最大限度地降低复杂性,维护和编程时间。这是最简单,最快捷的解决方案,因此只有在您以后确定其瓶颈时才能使用它来启动然后进行优化。