无法读回使用-migratePersistentStore withType:NSInMemoryStoreType编写的SQLite文件

时间:2014-11-29 23:49:06

标签: core-data

(我的问题有点类似于this one,除了我没有使用UndoManager,并且建议的解决方案对我不起作用。)

我的应用从第三方应用导入数据并将其存储在内存中,直到用户保存为止。导入定期在后台线程上保存:自己的managedObjectContext。该MOC使用其父级NSPersistentDocument MOC的持久性存储协调器。为了避免写入磁盘上的临时文件,使用NSInMemoryStoreType类型添加持久性存储。当用户想要将数据实际保存到磁盘上的文件时,在NSPersistentDocument的writeToURL覆盖中调用migratePersistentStore withType:NSInMemoryStoreType。

只要我使用NSXMLStoreType进行书写和阅读(在下面的代码中为// 1和// 2),这一切都可以正常工作。

当我切换到NSSQLiteStoreType时,写入会生成一个包含所有正确数据的有效SQLite文件,但回读该文件失败并显示以下错误:

CoreData: error: Encountered exception I/O error for database at /a/b/c.dat.  SQLite error code:14, 'unable to open database file' with userInfo {
NSFilePath = "/a/b/c.dat";
NSSQLiteErrorDomain = 14;
} while checking table name from store: <NSSQLiteConnection: 0x6080001e3300>

CoreData: error: -addPersistentStoreWithType:SQLite configuration:(null) URL:file:///a/b/c.dat options:{
    NSMigratePersistentStoresAutomaticallyOption = 1;
    NSReadOnlyPersistentStoreOption = 1;
} ... returned error Error Domain=NSCocoaErrorDomain Code=256 "The file couldn’t be opened." UserInfo=0x60800006df40 {NSSQLiteErrorDomain=14, NSUnderlyingException=I/O error for database at /a/b/c.dat.  SQLite error code:14, 'unable to open database file'} with userInfo dictionary {
    NSSQLiteErrorDomain = 14;
    NSUnderlyingException = "I/O error for database at /a/b/c.dat.  SQLite error code:14, 'unable to open database file'";

以下是相关的简化代码:

// NSPersistentDocument.m

- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError *__autoreleasing *)error {
    NSError *err;
    NSDictionary *opts = @{
                        NSMigratePersistentStoresAutomaticallyOption      : @YES,// it doesn't matter if these options are set or not
               NSReadOnlyPersistentStoreOption               : @YES,
                       }; 
    if (![self.managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType //1
                                                                            configuration:nil
                                                                                      URL:absoluteURL
                                                                                  options:opts
                                                                                    error:&err])
    {
        return NO;
    } else {
        return YES;
    }
}

- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError *__autoreleasing *)error {

     NSDictionary *opts = @{
                NSMigratePersistentStoresAutomaticallyOption      : @YES,// it doesn't matter if these options are set or not
                NSReadOnlyPersistentStoreOption          : @YES,
                                 };
        NSError *err;
     [self.managedObjectContext.persistentStoreCoordinator migratePersistentStore:self.managedObjectContext.persistentStoreCoordinator.persistentStores[0]
                                                toURL:absoluteURL
                                              options:opts
                                             withType:NSSQLiteStoreType //2
                                                error:&err];
     return YES;
}



// ====================================
// NSOperation.m


- (void)main
{
    [...]
    self.managedObjectContext                               = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    self.managedObjectContext.persistentStoreCoordinator                = self.myDoc.managedObjectContext.persistentStoreCoordinator;
    self.managedObjectContext.undoManager                     = nil;

    [self.managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType
                                                                       configuration:nil
                                                                                 URL:nil
                                                                             options:nil
                                                                               error:nil];

典型的数据库由30k个对象组成,使用XML时需要花费很长时间才能编写和读取,所以我需要使用SQLite类型。

欢迎任何建议。

1 个答案:

答案 0 :(得分:0)

我通过在-writeToUrl方法中使用以下dict解决了这个问题:

NSDictionary *opts = @{NSSQLitePragmasOption: @{@"journal_mode":@"DELETE"}};