我有一个Core Data后端,表现出一些奇怪的行为。我第一次运行我的应用程序(在模拟器中)我的NSFetchRequest永远不会找到匹配,即使连续多次给出相同的项目(它将返回'无结果'每个请求然后继续将重复信息插入数据库 - 我可以看到发生,因为我有一个与数据库绑定的tableview。)
如果我通过按主页按钮“退出”应用程序,然后重新打开应用程序。它开始按预期运行(在适当的情况下返回结果)。我也可以删除该应用程序,然后从Xcode再次运行它以将此过程重置为开头。它似乎不会保存数据库,直到应用程序关闭,即使我在NSManagedObjectContext上调用save(返回true)。
这里发生了什么?如何按预期工作?我想我只是不保存我对NSManagedObjectContext的更改,但我该怎么做?
+ (Mark *)markWithTWLInfo:(NSDictionary *)markDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
{
Mark *mark = nil;
NSLog(@"Starting Operation for Key: %@", [markDictionary[JS_MARK_ID] description]);
// Build a fetch request to see if we can find this Mark in the database.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Mark"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:@"idUnique = %@", [markDictionary[JS_MARK_ID] description]];
// Execute the fetch
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
// Check what happened in the fetch
if (!matches || ([matches count] > 1) || error ) { // nil means fetch failed; more than one impossible (unique!)
// handle error
if (error) {
NSLog(@"Fetch error: %@", [error description]);
} else {
NSLog(@"Found No/Multiple matches for key: %@", [markDictionary[JS_MARK_ID] description]);
}
} else if (![matches count]) { // none found, so let's create a mark
NSLog(@"Inserting: %@", [markDictionary[JS_MARK_ID] description]);
mark = [NSEntityDescription insertNewObjectForEntityForName:@"Mark" inManagedObjectContext:context];
mark.idUnique = [NSNumber numberWithInt:[markDictionary[JS_MARK_ID] intValue]];
//Save the changes; this returns True
if ([context save:&error]) {
NSLog(@"Saved is true");
} else {
NSLog(@"Saved is false");
}
if (error) {
NSLog(@"Save error: %@", [error description]);
}
} else { // found the mark, just return it from the list of matches (which there will only be one of)
NSLog(@"Found existing object for key: %@", [markDictionary[JS_MARK_ID] description]);
mark = [matches lastObject];
}
return mark;
}
for (NSDictionary *mark in results) {
if (DEMO_LOGGING) NSLog(@"Inserting: %@",[mark objectForKey:@"Mark"]);
[self.managedObjectContext performBlock:^{
[Mark markWithTWLInfo:[mark objectForKey:@"Mark"] inManagedObjectContext:self.managedObjectContext];
}];
}
- 使用新数据库启动应用程序:
2013-05-05 16:45:08.105 ToWatchList[10155:c07] Starting Operation for Key: 731
2013-05-05 16:45:08.106 ToWatchList[10155:c07] Inserting: 731
2013-05-05 16:45:08.111 ToWatchList[10155:c07] Saved is true
2013-05-05 16:45:10.651 ToWatchList[10155:c07] Starting Operation for Key: 731
2013-05-05 16:45:10.652 ToWatchList[10155:c07] Inserting: 731
2013-05-05 16:45:10.654 ToWatchList[10155:c07] Saved is true
-quit并重新启动程序
2013-05-05 16:45:29.816 ToWatchList[10155:c07] Starting Operation for Key: 731
2013-05-05 16:45:29.817 ToWatchList[10155:c07] Found No/Multiple matches for key: 731
- NSFetchRequest按预期返回我之前的2个条目,但它应该在尝试插入第二个条目时看到第一个条目。
答案 0 :(得分:4)
我的猜测是你的self.managedObjectContext
有一个父背景。
如果是这种情况,为了确保属性的唯一性,您必须一直保存到商店(递归保存直到不存在parentContext
)。
请注意,您必须等待保存在所有父上下文中完成,然后才能确保唯一性。
将您的[context save:&error]
替换为:
NSManagedObjectContext* c = context;
__block BOOL success = YES;
while (c && success) {
[c performBlockAndWait:^{
success = [c save:&error];
//handle save success/failure
}];
c = c.parentContext;
}