Core data 核心数据设计-如何同时拥有应用程序数据和用户数据?
我的应用程序附带了一组基本信息。用户可以添加或编辑此信息。但有时,我需要能够更新基础数据。我不想触碰用户更改/添加。我已经看过了,但是使用的类比有点陌生 这一定是一个常见的问题,我希望能听到这种混合数据集的实践和经验 当用户修改了一个对象时,我正在考虑为每个记录设置一个标志。然而,这带来了一个问题,即他们可能是意外地这样做的 我还可以创建两个数据集,但这会带来重复问题Core data 核心数据设计-如何同时拥有应用程序数据和用户数据?,core-data,ios7,database-design,Core Data,Ios7,Database Design,我的应用程序附带了一组基本信息。用户可以添加或编辑此信息。但有时,我需要能够更新基础数据。我不想触碰用户更改/添加。我已经看过了,但是使用的类比有点陌生 这一定是一个常见的问题,我希望能听到这种混合数据集的实践和经验 当用户修改了一个对象时,我正在考虑为每个记录设置一个标志。然而,这带来了一个问题,即他们可能是意外地这样做的 我还可以创建两个数据集,但这会带来重复问题 所以想法是最受欢迎的。所以从我所能告诉你的,你有4个要求(实际上,可能是4个不同的问题) 应用程序数据和用户数据应分开保存 应用
所以想法是最受欢迎的。所以从我所能告诉你的,你有4个要求(实际上,可能是4个不同的问题)
,其他子目录属于该目录
这对核心数据应用程序意味着什么?
用户数据和应用程序数据应在不同的位置使用不同的存储文件。您仍将使用一个NSPersistentStoreCoordinator,但向其中添加两个不同的持久存储。您的托管对象模型将需要两种不同的配置—每个存储都有自己的配置,每个实体都连接到其中一种配置
配置:
这将推动数据模型的设计-您不应该在两个不同的存储中存在单一实体类型,这意味着您将无法在用户存储中存在“用户编辑的Foo实体”,而在应用程序存储中存在“应用程序提供的Foo实体”-除非Foo是抽象的,每个商店都有自己的具体实体(这只是一个可能的解决方案)。
跨存储关系可以实现为获取的属性(稍后将详细介绍)
由于核心数据SQLite持久存储不是单个文件,而是文件的集合,因此建议每个存储都有自己的存储文件目录-这使得保存、删除、备份、应用程序更新等更加高效和可靠。
考虑到这一点,您的文件结构应该如下所示:
应用程序存储URL:
以确保在将来的版本中修复此问题。获取的属性对于遵守数据存储指南至关重要
应用程序附带一组“基本”数据
有多种方法可以处理此问题:
从JSON/XML/property list/CSV/等数据创建托管对象,并插入托管对象上下文并保存
除了用户和应用程序存储之外,还可以将存储作为只读存储
除了用户存储和应用程序存储之外,还可以使用一组预构建的SQLite文件(例如来自命令行工具)作为只读存储
从3中的预构建存储开始,但执行迁移以将这些对象移动到另一个存储中
各有优缺点:
这可能是缓慢、复杂、难以维护且容易出错的。这是一种更常见的方法,也是最糟糕的方法之一。认真地但如果这是你最容易维护的,那就给你更多的动力
还记得我之前说过给定实体不应该存在于多个存储/配置中吗?我没有告诉你全部真相。给定实体应仅存在于单个可写存储中。对于我们的Foo实体,我们可以有一个可写存储,但可以有任意多个只读存储。如果使用选项nsreadonlypersistentstoreption
将存储添加到持久存储协调器中,则该存储将是只读的。这意味着您可以使用预构建的NSSQLiteStore,该NSSQLiteStore是只读的,并且包含“初学者”数据,或者您也可以更雄心勃勃地使用可以读取其他数据格式的NSAtomicStore或NSIncrementalStore实现。这是最不容易出错的解决方案,也是最容易维护的解决方案之一李>
要为此创建一组SQLite文件,您需要构建一个工具,将大部分核心数据代码和托管对象模型作为应用程序共享。否则这与3相同
您可以在存储(如选项2或3中使用的存储)之间执行迁移,并使用迁移将数据移动到应用程序或用户存储中。迁移通常比执行类似选项1的操作性能更高,尽管它们有一些限制:例如,轻量级迁移可以很好地工作,但无法防止重复或冲突。需要进行自定义迁移。这样的迁移如下所示:sqlStore=[persistentstorecordinator migratePersistentStore:store-tour:[self-applicationStoreURL]选项:nil with-type:NSSQLiteStoreType-error:&error]
其中store
是已添加到协调器的源存储(此操作将删除它,并添加迁移的存储)。这将有效地将store
的内容注入applicationStoreURL的NSSQLiteStoreType
存储区
阿普里卡
- (NSURL *)supportFilesDirectoryURL {
NSURL *result = nil;
NSURL *applicationSupportDirectoryURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
NSString *bundleName = [[NSBundle bundleForClass:[self class]] bundleIdentifier];
result = [applicationSupportDirectoryURL URLByAppendingPathComponent:bundleName isDirectory:@YES];
return result;
}
- (NSURL *) applicationStoreURL {
NSError *error = nil;
NSFileCoordinator *coordinator = nil;
__block BOOL didCreateDirectory = NO;
NSURL *supportDirectoryURL = [self supportFilesDirectoryURL];
NSURL *storeDirectoryURL = [supportDirectoryURL URLByAppendingPathComponent:@"ApplicationData" isDirectory:YES];
coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[coordinator coordinateWritingItemAtURL:storeDirectoryURL options:NSFileCoordinatorWritingForDeleting error:&error byAccessor:^(NSURL *writingURL){
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *fileError = nil;
if (![fileManager createDirectoryAtURL:writingURL withIntermediateDirectories:YES attributes:nil error:&fileError]){
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Handle the error
}];
} else {
// Setting NSURLIsExcludedFromBackupKey on the directory will exclude all items in this directory
// from backups. It will also prevent them from being purged in low space conditions. Because of this,
// the files inside this directory should be purged by the application.
[writingURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&fileError];
didCreateDirectory = YES;
}
}];
// See NSFileCoordinator.h for an explanation.
if (didCreateDirectory == NO){
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Handle the error.
}];
}
return [NSURL URLWithString:@"Application.sqlite" relativeToURL:storeDirectoryURL ];
}
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"Application" URL:[self applicationStoreURL] options:nil error:&error]) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Handle the error.
}];
}
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"User" URL:[self userStoreURL] options:nil error:&error]) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Handle the error.
}];
}