Magical Records:加载要在本地上下文中更新的记录

Posted

技术标签:

【中文标题】Magical Records:加载要在本地上下文中更新的记录【英文标题】:Magical Records: Loading a record to be updated in a local context 【发布时间】:2014-09-19 15:23:27 【问题描述】:

我目前正在使用 Magical Records 保存记录,如下所示:

NSManagedObjectID *objID = [existingItem objectID];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
    CustomNSMO *item;
    if(newItem) item = [CustomNSMO MR_createEntityInContext:localContext];
    else item = [localContext objectWithID:objID]; 
    item.sync = 1;
    item.relID = @"Some String";
 completion:^(BOOL success, NSError *error) 
   //do something
 ];

这很好用。如果我查询所有设置了 sync 的项目,我会得到我期望的结果,即

  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(sync >= 1)"];
  NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate];

给我一​​个我的新对象或更新对象的数组。

然后我(在一些服务器业务之后)想要找到所有 sync >= 1 的结果并将其设置为零。这是发生奇怪行为的时候。我一直在尝试通过任一方式在本地上下文中获取一系列结果

  NSManagedObjectContext *localContext    = [NSManagedObjectContext MR_context];
  NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate inContext:localContext];
  for(CustomNSMO *item in objects) 
     item.sync = 0;
  
  [localContext MR_saveToPersistentStoreAndWait];

  [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
    NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate inContext:localContext];
    for (SyncObject *currentObj in objects)
    
        currentObj.sync = @0;
    
   completion:nil];

如果在第一次创建项目时设置了 relID,那么这一切都很好。我可以编辑项目(更改 relID)并且在所有上下文中都可以观察到更改。但是,如果第一次创建项目时,它的 relIDnil,那么在使用上面的代码执行以下操作后会出现问题:

1) 更新项目,将 nil relID 更改为某个非nil

2) 将项目保存到数据库中

3) 加载项目(通过搜索'sync')

MR_defaultContext 之外的任何上下文中,relID 保持为 nil。如果我查看 MR_defaultContext 中的对象,我会看到正确更新的 relID。如果我在不同的上下文中查看它,它是 nil。这意味着本地上下文中 sync 的更新会覆盖默认上下文中 relID 的值(将其设置为 nil)。

【问题讨论】:

【参考方案1】:

一些想法:

if(newItem) item = [CustomNSMO MR_createEntityInContext:context];

应该是:

if(newItem) item = [CustomNSMO MR_createEntityInContext:localContext];

您不想在 +saveWithBlock: 中使用不同的上下文。

另外,这一行:

else item = [localContext objectID];

我想你的意思是[localContext objectWithID:objID][localContext existingObjectWithID:objID error:error]

【讨论】:

您是对的,但这些只是我的示例中的拼写错误(我简化了原始代码)。我已经编辑了上面的代码。 好的,接下来请确保您在没有看到更新值的上下文中刷新/重新获取,或者观察 contextDidSave 通知并合并更改。 我没有看到更改的上下文是在我更改 sync 属性并重新保存之前创建的。我原以为此上下文将基于 MR_defaultContext 的值(确实显示了更改),因此不需要任何合并。基本过程是saveWithBlock,然后再次完成saveWithBlock。第二个块的上下文不反映第一个块的变化。但是在第二个块中查询 defaultContext 确实显示了第一个块的变化。 Nick,你可以尝试将 MagicalRecord 更新到 2.3 版吗? 不使用[NSManagedObjectContext MR_context],而是分配并初始化具有适当并发类型的上下文,并将其parentContext属性设置为MR_defaultContext【参考方案2】:

原来这是我们在 Core Data 下使用的数据库存储的一个错误。

https://github.com/project-imas/encrypted-core-data/issues/118

【讨论】:

以上是关于Magical Records:加载要在本地上下文中更新的记录的主要内容,如果未能解决你的问题,请参考以下文章

Magical Records - 如何使用关键路径映射关系?

我正在尝试从 Magical Records 获取最新添加的数据

Magical Record添加对象,不同的上下文错误

Magical Record 检测到默认上下文没有变化

Magical Record IOS 目标 C. 我们应该创建啥上下文?

使用 Swift 3 在 Magical Record 中保存上下文时出错