【问题标题】:Core Data - Relationships between Multiple Core Data Models核心数据 - 多个核心数据模型之间的关系
【发布时间】:2017-12-11 01:18:54
【问题描述】:

平台

iOS 10、Xcode 8.3.3

背景

我已经构建了一个利用 Core Data 的 Notes 应用程序,我想在我的下一个应用程序中使用这个应用程序,该应用程序也将使用 Core Data。为简单起见,我们将下一个应用程序称为“ListApp”,将笔记应用程序称为“NotesApp”。这个 ListApp 有列表项,每个项都可以有一个或多个注释。

这是我到目前为止所做的:

  1. 从 NotesApp 中删除了所有不必要的文件并编译了“NotesApp 框架”。
  2. 将 NotesApp 框架链接到 ListApp。
  3. 为 ListApp 设计了核心数据模型。具体来说,我创建了一个名为“ListItem”的实体和一个名为“Note”的实体。 ListItem 与 Note 具有一对多的关系(一个列表项可以有多个注释)。 Note 实体包含一个“noteID”字段来引用 NotesApp 模型中的便笺,当然还有反向关系。

问题

我需要在 ListApp 模型中的实体和 NotesApp 模型中的实体之间建立“关系”。

我研究了配置,这似乎更适合将同一模型中的对象存储到不同的持久存储中,除非我缺少某些东西。所以,这没有帮助。

然后,我发现获取的属性可以用来在多个商店之间形成弱关系。所以,这也无济于事。

接下来,我在文档中发现有一个名为 NSManagedObjectModel.mergedModel(from:) 的方法,所以我假设这是可能的。或者也许这只是为了迁移?

这就是我卡住的地方。

原因

我不希望将 NotesApp 模型中的所有内容都重新设计为 ListApp 模型。我更喜欢将所有内容分开。

问题

有没有办法在不同模型中的两个实体之间建立关系?我是否应该在 ListItem 实体类中添加一个函数来手动获取 NotesApp 模型中的注释?我是在走正确的道路还是有更好的选择?

注意:我所说的“关系”是指能够调用 ListItem 实体中的属性来获取注释并以某种方式将特定注释“关联”到一个特定的 ListItem。

P.S.如果您知道任何陷阱、有任何一般性建议或知道任何阅读材料,请随时告诉我。

另外,我已经研究了这个话题几个小时,但我似乎找不到任何关于它的信息。我假设这是因为这是不可能的,这是一种糟糕的做法,或者我没有使用正确的关键字。

如果有人需要更多信息,请随时告诉我!

【问题讨论】:

    标签: ios objective-c iphone swift core-data


    【解决方案1】:

    我认为您的意思是您的捆绑包将有一个包含 List 实体的模型和另一个包含 Note 实体的模型。您可以按照您的建议合并和调整托管对象模型,并使用您在代码中拥有的生成的托管对象模型。

    • 如果您在代码中创建 Core Data 堆栈(也就是说,您没有使用新的 NSPersistentContainer),则可以轻松拼接到自定义托管对象模型中。
    • 如果您使用 NSPersistentContainer,则必须对其进行子类化并覆盖 managedObjectModel()。我找不到任何文件说你不能这样做,但我不会打赌。
    • 如果您是基于文档的,覆盖 UIDocument 的 managedObjectModel 应该可以工作。

    要创建您的自定义托管对象模型,请使用 NSManagedObjectModel.mergedModel(from:) 合并您的模型。然后,获取 Note 和 List 实体描述,获取每个实体的属性,变异,添加新关系,然后将它们设置回模型中。你只会在第一次运行时这样做;将您的自定义托管模型缓存到 ivar 以供后续运行。

    嗯嗯。我刚刚描述的,基本上是拆开、调整和重新组装该托管对象模型,将是相当多的代码行。如果这真的只是一个简单的“笔记和列表”应用程序,并且如果这只是这两个实体,那么放弃那些 .mom 文件并在代码中从头开始创建整个托管对象模型可能会更少代码。这并不难。戴上你的 Objective-C 眼镜,看看main.m of Apple's old Core Data Utility sample project 中的managedObjectModel() 函数。

    【讨论】:

    • 你的建议是我正在尝试做的事情。到目前为止,我已经使用您建议的方法合并了两个模型。然后,在使用 managedObjectModel 之前,我在 ListApp 模型中的 Note 实体上添加了一个 fetched 属性,以从 NotesApp 模型中获取实际的笔记。原因是我读过不支持跨商店关系。我认为这会起作用,但我还没有机会测试它。我的应用程序比前面提到的要复杂得多,但我简化了它以强调问题。感谢您的建议!
    • 虽然,在重新阅读您的答案后,不会有多个商​​店,因为我正在合并模型......嗯......
    • 我让它工作了。谢谢您的帮助!我会接受你的回答。
    【解决方案2】:

    好吧,原来我对 Core Data Stack 有一点误解,但这是一个非常简单的任务。根据一些研究和@Jerry Krinock 的回答,我能够非常轻松地完成这项工作。

    1. 创建一个框架,其中包含来自 NotesApp 的所需文件。
    2. 将框架链接到 ListApp。
    3. 获取对 ListApp 和 NotesApp NSManagedObjectModel可变 引用。
    4. 以编程方式在 ListApp 模型中的 ListItem 实体和 NotesApp 模型中的 Note 实体之间添加 NSRelationshipDescription(反之亦然)。
    5. 通过合并 ListApp 和 NotesApp 模型创建 NSManagedObjectModel

    注意:正如@Jerry Krinock 提到的,这只需要完成一次,因为我们将两个模型合并在一起并将它们存储在同一个持久存储中。这与通过 CoreData Model Builder UI 执行此操作相同,但以编程方式除外,因为它不支持从单独的模型中引用实体(至少我不知道或找不到)。

    参考资料:

    Core Data Programming Guide

    Core Data stack

    Universal Cocoa Touch Frameworks for iOS8 – (Remix)

    Adding relationships in NSManagedObjectModel to programmatically created NSEntityDescription

    目标-C:

        NSManagedObjectModel * listModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[self listModelURL]] mutableCopy];
        NSManagedObjectModel * notesModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[self notesModelURL]] mutableCopy];
    
        NSEntityDescription * listEntity = [listModel.entitiesByName objectForKey:NSStringFromClass([JBListItemMO class])];
    
        // The framework name is prepended to the class name. Remove it before getting the note's entityDescription.
        NSString * noteClassName = [NSStringFromClass([JPSNoteMO class]) componentsSeparatedByString:@"."].lastObject;
        NSEntityDescription * noteEntity = [notesModel.entitiesByName objectForKey:noteClassName];
    
        NSRelationshipDescription * whichListRelationship = [[NSRelationshipDescription alloc] init];
        whichListRelationship.minCount = 0;
        whichListRelationship.maxCount = 1;
        whichListRelationship.optional = NO;
        whichListRelationship.name = @"whichList";
        whichListRelationship.destinationEntity = listEntity;
        whichListRelationship.deleteRule = NSNullifyDeleteRule;
    
        NSRelationshipDescription * notesRelationship = [[NSRelationshipDescription alloc] init];
        notesRelationship.ordered = NO;
        notesRelationship.maxCount = 0;
        notesRelationship.minCount = 0;
        notesRelationship.optional = YES;
        notesRelationship.name = @"notes";
        notesRelationship.destinationEntity = noteEntity;
        notesRelationship.deleteRule = NSCascadeDeleteRule;
        notesRelationship.inverseRelationship = whichListRelationship;
    
        whichListRelationship.inverseRelationship = notesRelationship;
    
        listEntity.properties = [listEntity.properties arrayByAddingObject: notesRelationship];
        noteEntity.properties = [noteEntity.properties arrayByAddingObject: whichListRelationship];
    
        self.managedObjectModel = [NSManagedObjectModel modelByMergingModels:@[listModel, notesModel]];
    

    我将在完成 CoreDataStack 类的转换后发布 Swift 3 代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多