是否可以在一个iOS应用程序上拥有多个核心数据“数据库”?

时间:2012-10-28 13:40:25

标签: core-data nsmanagedobject multiple-databases nsentitydescription

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

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

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

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

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

数据架构不会改变。

所以我们有:

  1. 仅用于播种游戏的预定义数据(默认数据)。
  2. 用户当前的保存游戏。
  3. 用户已从互联网下载了一个场景。
  4. 问题:当用户在“场景”中保存游戏时会发生什么。
  5. 问题:如何跟踪核心数据中的所有场景和所有用户保存的游戏?
  6. 这听起来像是在给定时间的多个数据库。显然,应该限制用户可以制作多少个保存游戏。

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

    但我想从一开始就想知道在iOS设备上使用Core数据的最佳方法是处理1个以上的核心数据“数据库”吗?

    感谢您的时间

2 个答案:

答案 0 :(得分:3)

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

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

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

查看文档here以获取更多信息。


修改

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

答案 1 :(得分:1)

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

实际上,这并不意味着需要多个数据库。所以我们有:

  

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)。仅使用 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
    }];
  

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

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

  

问题:如何跟踪所有方案和所有用户   在核心数据中保存了游戏?

数据建模可能很棘手。最初保持简单,并在发现明确需要时添加表和关系。然后测试,测试,测试。