【问题标题】:Core Data migration not persisting new attribute核心数据迁移不保留新属性
【发布时间】:2025-08-30 18:10:02
【问题描述】:

我正在执行 Core Data 轻量级迁移,向现有对象添加新属性。例如,假设我有歌曲和播放列表,两者之间存在多对多关系(即歌曲可以位于多个播放列表中,并且播放列表包含多首歌曲)。

我添加了一个新的 Core Data 模型版本,然后添加了一个名为 songCount 的新播放列表属性。我手动将该属性添加到我的模型类中,然后覆盖 CoreDataGeneratedAccessors 以将新的Song 添加到Playlist,如下所示:

@dynamic songCount;

- (void)addSongObject:(Song *)value
{
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];

    [self willChangeValueForKey:@"songs"
                withSetMutation:NSKeyValueUnionSetMutation
                   usingObjects:changedObjects];
    [[self primitiveSongs] addObject:value];
    [self didChangeValueForKey:@"songs"
               withSetMutation:NSKeyValueUnionSetMutation
                  usingObjects:changedObjects];

    // don't think the broadcasts are necessary when using the setter
    [self willChangeValueForKey:@"songCount"];
    self.songCount = @([[self primitiveSongs] count]);
    [self didChangeValueForKey:@"songCount"];
}

这一切正常。当我将歌曲添加到播放列表,然后对播放列表进行 Core Data 提取时,播放列表具有正确的 songCount 值(我什至可以按歌曲数量对提取进行排序,这就是重点)。

但是,当我重新启动应用程序时,我所有播放列表的 songCount 属性都是 nil。我错过了什么?我做了一个[context save],播放列表确实包含新歌,只是没有保存歌曲数。它不是临时属性,persistentStoreCoordinator 不会抱怨迁移。我不确定还有什么问题,或者在哪里寻找调试。

【问题讨论】:

  • 尽量不要覆盖生成的访问器并手动添加歌曲计数。如果它仍然存在,则您的覆盖有问题。 [playlist addSongObject:song]; playlist.songCount = @(playlist.songCount.integerValue +1);

标签: ios core-data migration


【解决方案1】:

我通过记录与歌曲和播放列表关联的托管对象上下文发现了问题。它们是不同的,所以[context save] 保存的是新歌曲,而不是它添加到的播放列表。 Core Data 通过将歌曲添加到播放列表的反向关系自动为我修复了一致性问题,但它没有自动更新songCount。不要问我为什么我的应用中有两个不同的托管对象上下文。

【讨论】: