【问题标题】:Is it possible to have multiple core data "databases" on one iOS app?是否可以在一个 iOS 应用程序上拥有多个核心数据“数据库”?
【发布时间】:2012-10-28 13:40:25
【问题描述】:

我想编写一个大量使用核心数据的“管理”游戏。游戏需要用户/系统无法更改的预设、预定义数据集;它用于为游戏播种数据,并且是只读的。

我能举出的最好的例子是足球管理游戏,但它可以是任何东西。在一些足球管理模拟游戏中,它们会为您提供场景和预设数据集。

当用户继续游戏时,他们可以保存/加载他们的进度,这些进度会保存到核心数据中。

除此之外,用户可以接收预定义数据的更新或购买场景数据包;已保存到他们的设备中。

因此,可能有多个“核心数据数据库”(是的,我知道核心数据并不是严格意义上的数据库)或应用可以深入使用的“存储桶”。

数据的架构不会改变。

所以我们有:

  1. 仅用于播种游戏的预定义数据(默认数据)。
  2. 用户当前保存的游戏。
  3. 用户从 Internet 下载了一个场景。
  4. 问题:当用户在“场景”中保存游戏时会发生什么。
  5. 问题:如何在核心数据中跟踪所有场景和所有用户保存的游戏?

这听起来像是在给定时间有多个数据库。显然应该限制一个用户可以制作多少个存档游戏。

对此的另一种解决方案是,用户的设备以 JSON 或 XML 格式导出数据的备份副本,并将其用作“保存数据”,我也可以将此策略用于场景。显然需要某种加密来防止人们通过 XML 简单地更改游戏中的统计数据。

但我从一开始就想知道,使用 iOS 设备的核心数据处理多个核心数据“数据库”的最佳方式是什么?

感谢您的宝贵时间

【问题讨论】:

    标签: core-data nsmanagedobject multiple-databases nsentitydescription


    【解决方案1】:

    如果数据模型相同,您只需设置 MOC,使其同时使用两个持久存储...一个是只读的,另一个是读/写的。

    或者,您可以为每个商店使用单独的 MOC。

    因此,您想如何使用它是您唯一的决定因素,因为您几乎可以拥有 MOC/PSC 的任何组合。

    查看文档here 了解更多信息。


    编辑

    此问题给出的链接已失效,其他人在另一个已删除的答案中建议this link

    【讨论】:

    • 是的,数据模型是一样的。我喜欢使用持久存储的想法。我对它们了解不多,但我会阅读它们,
    • 该文档非常好,因为我的结构类似于公司、员工和部门。我想我会接受你的回答并阅读更多关于持久存储的内容
    • @Danh - 感谢您的编辑。我将原始链接更改为另一个核心数据链接,但两者都与原始链接不同。
    【解决方案2】:

    注意:这是一个老问题,但它描述的问题是永恒的,所以我写了答案,就好像问题是今天发布的一样。

    实际上,这些都不表明需要多个数据库。所以我们有:

    1) 仅用于播种的预定义数据(默认数据) 游戏。

    编写一个将数据加载到持久存储(数据库)中的方法。在用户默认、defaultDataHasBeenLoaded 或类似的东西中设置一个标志,并在 appDelegata 中检查。

    2) 用户当前保存的游戏。

    您需要具有一对多关系的 Users 表和 Games 表。在 Games 表中添加 isCurrentGame 属性。

    3) 用户从互联网上下载了一个场景。

    现在变得有趣了。您将需要一个导入函数或类,并且您需要在后台线程上运行它。这样,您的用户可以在导入新场景的同时继续玩游戏,或者查看他们的分数或其他内容。导入场景后,用户应该会收到通知并有机会切换到新场景。

    最有效的方法是使用 NSPeristentContainer,它适用于 iOS 10.0、macOS 10.12、tvOS 10.0 和 watchOS 3.0。为 NSPeristentContainer 提供数据模型的名称,它将创建或加载持久存储并设置 persistentStoreCoördinator 和 managedObjectContext。

    // AppDelegate.h or class header file
    @property (readonly, strong, nonatomic) NSPersistentContainer *persistentContainer;
    @property (readonly, weak, nonatomic) NSManagedObjectContext *managedObjectContext;
    
    
    // AppDelegate.m or other implementation file
    @synthesize persistentContainer = _ persistentContainer;
    @synthesize managedObjectContext = _ managedObjectContext;
    
    - (NSPersistentContainer *)persistentContainer
    {
        @synchronized (self) {
            if (_persistentContainer == nil) {
                _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"nameOfDataModel"];
                [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                    if (error != nil) {
                        // Handle the error
                    } else {
                        _managedObjectContext = _persistentContainer.viewContext; // NB new name for moc is viewContext!
                    }
                }];
            }
        }
        return _persistentContainer;
    }
    

    要在 NSViewController 中使用 appDelegate 中的容器,请将以下内容添加到 viewDidLoad:

    self.representedObject = [(AppDelegate *)[[NSApplication sharedApplication] delegate] persistentContainer]; 
    
    // Use representedObject in bindings, such as:
    [_gameNameTextField bind:NSValueBinding toObject:self
                      withKeyPath:@"representedObject.game.name"
                          options:options];
    

    要导入新场景,请使用 performBackgroundTask: 块,它会自动创建一个新线程和一个新 managedObjectContext(这里称为 moc_background)。 only moc_background 用于您在块中所做的任何事情——如果您在块外调用方法,请将其传递给 moc_background。

      NSPersistentContainer *pc = (NSPersistentContainer *)self.representedObject;
        pc.viewContext.automaticallyMergesChangesFromParent = YES; // this will ensure the main context will updated automatically
    
        __block id newScenario;
        [pc performBackgroundTask:^(NSManagedObjectContext * _Nonnull moc_background) {
            NSEntityDescription *scenarioDesc = [NSEntityDescription entityForName:@"Scenario" inManagedObjectContext:moc_background];
            NSManagedObject *scenario = [[NSManagedObject alloc] initWithEntity:scenarioDesc insertIntoManagedObjectContext:moc_background];
            // configure scenario with the data from newScenario
    
            NSError *error;
            BOOL saved = [moc_background save:&error];
            // send out a notification to let the rest of the app know whether the import was successfull
        }];
    

    问题:当用户保存游戏时会发生什么? “情景”。

    这取决于谁先到达那里,尝试合并的后台线程或保存操作。如果将具有多对一关系的 Scenario 表添加到 Game 表中,应该不会有任何问题。

    问题:我如何跟踪所有场景和所有用户 在核心数据中保存游戏?

    数据建模可能很棘手。一开始保持简单,当您发现明确需要时添加表格和关系。然后测试,测试,测试。

    【讨论】:

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