CoreData 在启动时检测数据库不一致

CoreData detect database inconsistency on start up

我们有一些代码可以确定当前是否没有创建数据库文件。如果是这种情况,我们会根据文件系统上可能存在的一些文件执行一些初始化例程来填充用户的数据库(基本上是迁移例程)。

套路基本是这样

NSURL * defaultStorePath = [NSPersistentStore MR_defaultLocalStoreUrl];
BOOL initializeDatabase = ![[NSFileManager defaultManager] fileExistsAtPath:[defaultStorePath path]];    

[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreAtURL:defaultStorePath];

if(initializeDatabase)
    // ... ingest user files ...

因此,如果 .sqlite 文件不存在,此方法效果很好。但是,如果 .sqlite-wal.sqlite-shm 文件是 missing/corrupt,我们无法找到检测这种情况的方法。

在这种情况下,我们想进行数据完整性检查或其他操作。

没有MagicalRecord:

NSURL *storeURL = ...
NSError *error;
NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];

if (persistentStore) {
    // further initialization
} else {
    switch (error.code) {
        case NSFileReadCorruptFileError: {
            NSLog(@"database corrupted.");
            // delete .sqlite, -wal and -shm
            // make another attempt to add persistent store
            break;
        }
        case NSPersistentStoreIncompatibleVersionHashError: {
            NSLog(@"database model updated.");
            // migrate
            break;
        }
        default: {
            NSLog(@"unresolved error %@", error.localizedDescription);
            abort();
        }
    }
}

举个例子,希望对你有帮助。

func configurePersistentStore() {
    let nc = NSNotificationCenter.defaultCenter()
    nc.addObserver(self, selector:#selector(self.dataBaseWillBeRecreated(_:)), name:kMagicalRecordPSCMismatchWillDeleteStore, object:nil)

    MagicalRecord.setLoggingLevel(MagicalRecordLoggingLevel.Warn)
    // if sqlite database does not match the model you provided, delete store.
    // MagicalRecord.setShouldDeleteStoreOnModelMismatch(true)
    MagicalRecord.setupCoreDataStackWithStoreNamed(kPersistentStoreName)

    if ESGlobal.sharedInstance().firstRun { // User first run your app after installation.
        self.fillDefaultDataToSQLiteDB() // fill data
    }
}