RestKit 和 CoreData 无法关闭日志模式的问题

Posted

技术标签:

【中文标题】RestKit 和 CoreData 无法关闭日志模式的问题【英文标题】:Issue with RestKit and CoreData unable to turn off journal mode 【发布时间】:2014-05-23 05:27:50 【问题描述】:

我刚开始使用 RestKit 框架 v0.20.3 与直接使用 Core Data。我正在尝试关闭日志模式以在 SQLite 数据库浏览器中查看数据库。我使用以下代码将 NSSQLitePragmaOption 设置为 @@"journal_mode":@"delete":

NSDictionary *options = @ NSMigratePersistentStoresAutomaticallyOption:@YES,
                           NSInferMappingModelAutomaticallyOption:@YES,
                           NSSQLitePragmasOption : @@"journal_mode": @"delete"
                         ;
NSError *error;
NSPersistentStore *persistentStore = [objectStore addSQLitePersistentStoreAtPath:storePath
                                                          fromSeedDatabaseAtPath:nil
                                                               withConfiguration:nil
                                                                         options:options
                                                                           error:&error];

然而,这似乎并没有关闭日志模式并删除 .sqlite-wal 文件。当我直接使用 Core Data 并添加此选项时,它可以完美运行。有什么我想念的吗?

【问题讨论】:

显示更多用于您的核心数据堆栈设置的代码以及此代码如何与 RestKit 链接。 【参考方案1】:

我发现 addPersistentStoreWithType 在 RestKit 的其他地方被调用,并且需要具有相同的选项才能禁用日志。就我而言,我使用RKManagedObjectImporter 创建一个种子数据库,如下所示:

NSError * error = nil;
NSString * seedFilePath = [[NSBundle mainBundle] pathForResource:@"seed" ofType:@"json"];

NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString * path = [documentsPath stringByAppendingPathComponent:@"MyDB.sqlite"];

RKManagedObjectImporter * importer = [[RKManagedObjectImporter alloc] initWithManagedObjectModel:_objectManager.managedObjectStore.managedObjectModel storePath:path];
[importer importObjectsFromItemAtPath:seedFilePath withMapping:mapping keyPath:keyPath error:&error];
BOOL success = [importer finishImporting:&error];
if (success) 
    [importer logSeedingInfo];
 else 
    RKLogError(@"Failed to finish import and save seed database due to error: %@", error);

即使对 RKManagedObjectStore 进行了上述更改,我仍然在这里看到 -shm 和 -wal 文件。它显然不关心用于创建_object_manager.managedObjectStore 类型为RKManagedObjectStore 的选项。

我发现,在RKManagedObjectImporter.m 中,createPersistentStoreCoordinator 方法也添加了自己的持久存储,所以我在其中添加了选项字典:

NSDictionary * options = @ NSSQLitePragmasOption : @ @"journal_mode" : @"DELETE"  ;
NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                              configuration:nil
                                                                                        URL:storeURL
                                                                                    options:options error:error];
if (! persistentStore) 
    return nil;

最终……嗯,这样做很关键,因为没有它,种子数据库将丢失数据。现在我的 -shm 和 -wal 文件不见了。谢谢,顺便说一句,上述答案帮助我找到了另一个位置。

【讨论】:

【参考方案2】:

我遇到了同样的问题。在 ios 6 中运行的代码突然开始在 iOS 7 中显示一些错误(数据丢失)。

我添加了NSSQLitePragmasOption: @ @"journal_mode": @"DELETE" 选项 RKManagedObjectStore 对象,但我仍然面临这个问题。

所以,在经历的时候

- (NSPersistentStore *)addSQLitePersistentStoreAtPath:(NSString *)storePath fromSeedDatabaseAtPath:(NSString *)seedPath withConfiguration:(NSString *)nilOrConfigurationName options:(NSDictionary *)nilOrOptions error:(NSError **)error

RKManagedObjectStore.m 类的方法,我发现了这条评论

/** 组合配置和迁移似乎有问题。所以分两步来做:首先,附加存储没有配置,但有迁移选项;然后删除它并重新附加 WITH 配置,但不是迁移选项。 **/

这里“persistentStore”被重新初始化,“seedOptions”跳过了我提供的“选项”。 所以对于我的项目,我不需要任何配置,所以我在下面的行中进行了评论,它开始工作了。

    if (! [self.persistentStoreCoordinator removePersistentStore:persistentStore error:error]) return nil;

NSDictionary *seedOptions = @ RKSQLitePersistentStoreSeedDatabasePathOption: (seedPath ?: [NSNull null]) ;
persistentStore = [self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nilOrConfigurationName URL:storeURL options:seedOptions error:error];
if (! persistentStore) return nil;

现在 wal 和 shm 文件没有生成,我的代码按预期工作。

希望这会有所帮助。

【讨论】:

以上是关于RestKit 和 CoreData 无法关闭日志模式的问题的主要内容,如果未能解决你的问题,请参考以下文章

RestKit:无法使用 coredata 执行映射

无法让 Restkit 0.20 + CoreData 工作

RestKit 0.20 无法从服务器获取数据

RestKit 和 Coredata

RestKit - 清除数据

CoreData 和 RestKit