NSManagedObject忽略已更改的可变形

时间:2014-07-16 17:56:17

标签: ios core-data nsmanagedobject magicalrecord

对于符合NSCoding的某些对象,我有一个非常基本的缓存系统。方法获取对象,提取键和搜索参数的一些信息,创建或更新NSManagedObject,并将其保存到持久存储:

CoreData model for SECachedQuestion

+ (void)updateQuestion:(StacManQuestion *)question site:(StacManSite *)site
{
    // 1. Look up with a basic predicate.
    SECachedQuestion *cachedQuestion = [SECachedQuestion 
        findFirstWithQuestionId:question.questionId site:site];

    // 2. Create if missing.
    if (!cachedQuestion) {
        cachedQuestion = [SECachedQuestion MR_createEntity];
        cachedQuestion.questionId = question.questionId;
        cachedQuestion.site = site.apiSiteParameter;
    }

    // 3. Update properties.
    cachedQuestion.isFavorite = question.favorited;
    cachedQuestion.lastAccessTime = [NSDate date];
    cachedQuestion.question = question;

    // 4. Save
    [[NSManagedObjectContext MR_contextForCurrentThread] 
        MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
        /* ... */
    }];
}

此代码第一次运行时,它完美运行。该对象将保存到缓存中,并立即可用于下一次运行。然而,在此之后,为cachedQuestion.question分配新值不会做任何事情。

我添加了一些断点并找到了以下内容:

  1. 问题分配不会更新changedValues

    (lldb) po [cachedQuestion changedValues]  {
        lastAccessTime = "2014-07-16 17:16:45 +0000";
    }
    
  2. questioncachedQuestion.question从不同的地址开始,然后以相同的方式结束,因此肯定会发生分配。

  3. 如果我在设置cachedQuestion.question = nil的作业之前放了一步,我会得到以下内容,但问题记录在重新分配时会再次消失。

    (lldb) po [cachedQuestion changedValues]  {
        lastAccessTime = "2014-07-16 17:16:45 +0000";
        question = "<null>";
    }
    
  4. 这是另一个超级的事情。我继续进行测试,我只为{+ 1}}设置应用程序的几个版本。这适用于单次运行中的后续查找,但每次应用程序启动时,第一次读取cachedQuestion.question都会返回到原始值!我可以确认是否已开始创建新的缓存问题 lastAccessTime没有问题更新。只是这一个字段被及时冻结。 这是因为数据验证。 cachedQuestion.question = nil让它显示更改后的值,但保存失败,因为它不是可选的。

  5. 更新

    现在我正在做一个悲伤的悲伤黑客,任何时候有变化我删除旧记录并插入一个新记录。它运作得很好,但我更想知道出了什么问题。

2 个答案:

答案 0 :(得分:0)

您没有将更改写入正确的上下文。首先,停止使用contextForCurrentThread。它已被弃用,并且会导致您在100次中出现1次崩溃,这太多了。您还冒着崩溃的风险,因为此方法可以并且将返回不是默认上下文的上下文。在各种情况下进行托管对象分配也会崩溃,这是有充分理由的。

相反,您应该明确创建上下文,将更改写入其中,然后在方法结束时保存它。这可能会解决你所看到的大部分问题。

答案 1 :(得分:0)

我不得不多次阅读这篇文章...... 我认为这里的问题是你没有正确使用关系。 应将NSManagedObjects设置为实体。

它不应该是可转换的,而是与实体的关系。

从上下文中,您可以获取MutableArray中第一个实体中的第一个所有对象,然后通过在选择一个对象时调用此关系,在对象的新MutableArray中获取所有相关对象:

self.newArray = [[self.oldObject.relationshipName allObjects] mutableCopy];

然后,您将只获取与所选对象相关的内容,而不是相关实体中的所有对象。

这意味着不应该有问题属性,而是与实体问题的关系。