【问题标题】:iPhone core data upsert from downloaded sqliteiPhone核心数据从下载的sqlite更新
【发布时间】:2011-03-07 15:33:20
【问题描述】:
我想介绍一下我的核心数据应用程序能够下载新的 sqlite 文件并更新其存储的数据。请注意,数据模型没有改变。
起初我并不担心用户对存储数据的更改,只是想覆盖它。
- 我发现更新存储数据的唯一方法是更改 sqlite 文件的名称..?
- 是否有一种通过核心数据合并 2 个 sqlite 文件的标准方法?从而保留用户修改过的数据。
- 更新(下载的 sqlite 文件)可以是交付的核心数据 sqlite 的子集吗?请注意,sqlite 包含二进制信息。
我认为this SO question 无法回答这些问题。
感谢您的指导!
【问题讨论】:
标签:
iphone
iphone-sdk-3.0
core-data
【解决方案1】:
我知道这是一个老问题,但我自己解决了这个问题后,我只想补充以下几点:
- 核心数据存储的默认 sqlite 文件 yourProjectName.sqlite 似乎受到保护。覆盖它不起作用。您需要按照 raaz 上面的建议进行操作并创建一个副本。
- 创建副本后,您可以轻松覆盖文件。但是,其他答案中的一些建议表明,覆盖核心数据 sqlite 文件的最佳方法是先将其删除。这在设备上不起作用!它抛出一个错误,说它无法删除文件。它可以在模拟器中运行,但不能在设备上运行(在 4.2 上的 3G 上测试)
- 因此,最好的方法是直接覆盖文件,而不是删除它并创建一个新文件。
- 当然,请务必先从持久存储协调器中删除存储!
我的 2c,希望对某人有所帮助。
【解决方案2】:
如果你想在不修改现有数据库的情况下更新任何数据库文件,那么你必须像这样实现
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self createEditableCopyOfDatabaseIfNeeded];
}
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence - we don't want to wipe out a user's DB
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentDirectory = [self applicationDocumentsDirectory];
NSString *writableDBPath = [documentDirectory stringByAppendingPathComponent:@"DataBaseName.sqlite"];
BOOL dbexits = [fileManager fileExistsAtPath:writableDBPath];
if (!dbexits) {
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"DataBaseName.sqlite"];
NSError *error;
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
}