【问题标题】:CoreData updating an NSManagedObject more than once saves several copies?CoreData 多次更新 NSManagedObject 会保存多个副本?
【发布时间】:2013-07-09 13:07:01
【问题描述】:

我有 90 个名为“ItemModel”的 CoreData 实体,具有 2 个属性“uid”、“description”,其中每个项目都作为 NSManagedObject 插入:

NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName: @"ItemModel" inManagedObjectContext: AFYDelegate.managedObjectContext];

第一个服务器调用将“uid”分配给上面为键“uid”提取的 90 个项目中的每一个。上下文没有保存在这里。

在稍后的第二次服务器调用中,我喜欢使用 indexPath 为 NSManagedObject 的 每个 更新 90 个项目的“描述” - 通过获取每个对象并将其传递给以下方法并保存上下文:

[self updateItemToDataModel:object withData: description];

....
....

- (void)updateItemToDataModel:(NSManagedObject *) object withData:(NSString *)data
{   
    [object setValue:data  forKey:@"description"];

    NSError * error = nil;
    if (![self.managedObjectContext save:&error]) {
       //Handle any error with the saving of the context
       NSLog(@"%@",error.localizedDescription);
    }
}

上述方法在关闭模拟器并再次运行代码后更新 CoreData 工作正常,每个项目将有两个重复项,具有相同的“uid”和“描述”。这意味着我现在有 180 件商品。反复关闭和​​运行代码会创建越来越多的项目。

我尝试删除 updateItemToDataModel 方法,重置模拟器,它适用于 90 个项目。

如果有人可以提供帮助,我是 CoreData 的新手。如果我只想更新现有项目,我的代码有什么问题?

【问题讨论】:

  • 您如何检索您的“对象”?你有那个代码吗?
  • 通过 UICollectionView 和 NSFetchedResultsController 中的 indexPath 检索对象 - NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] lastObject]; NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];

标签: ios nsmanagedobject insert-update


【解决方案1】:

您每次都将一个新对象插入到 MOC(托管对象上下文)中,而不是进行获取并查找您希望更新的对象的现有实例。

要获取现有对象,您可以像这样执行获取请求...

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"uid == %@", uidToMatch];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"ItemModel" inManagedObjectContext:managedObjectContext]];
NSError * error = nil;
NSArray * results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if ([results count]) {
    // you may need to handle more than one match in your code...
    // you could also set a fetch limit of 1 and guarantee you only get the first object, eg: [fetchRequest setFetchLimit:1];
}
else {
    // no results
}

您可能希望将其包装在一个辅助函数中,以便您可以重复使用它。并阅读 NSFetchRequest、NSPredicate 和编写谓词以执行更高级的获取请求。

【讨论】:

  • 太棒了!谢谢尼古拉斯!只是为了澄清 NSArray 结果是返回 NSManagedObject 类对象,我只是做 setValue?什么时候应该正确保存 self.managedObjectContext? - 是在 RootViewController 或 AppDelegate applicationWillTerminate 的 ViewDidUnload 处?
  • 它返回一个包含所有与指定实体名称和指定谓词匹配的托管对象的数组。在这种情况下,您的“ItemModel”对象。决定何时保存数据由您决定。保存可能会很昂贵,因此您希望等到用户完成更改(例如:关闭编辑界面时)。您可能不想等到您的应用程序关闭后再保存——因为如果它崩溃了,您将丢失所有数据。 (顺便说一句,永远不要依赖 viewDidUnload 或 applicationWillTerminate 被调用——不能保证它们会被调用。)
  • 再次感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多