最近のアプリの更新で、データベースを保存するときに非常に一貫性のない SQLite エラーが表示されるようになりました。これらは複数のユーザーで発生しているため、同じユーザーが繰り返しクラッシュするだけではありません (同じユーザーに対して複数回発生していますが)。SQLITE_IOERR_READ であるエラー 266 が発生しています。このエラーが発生した人は他にいないので、なぜエラーが発生するのかわかりません。
00:04:18:25 $ -[AppDelegate saveContext] line 328 $ Unresolved error Error Domain=NSCocoaErrorDomain Code=266 "The operation couldn’t be completed. (Cocoa error 266.)" UserInfo=0x1dd141b0 {NSSQLiteErrorDomain=266, NSFilePath=/var/mobile/Applications/[omitted], NSPOSIXErrorDomain=1, NSUnderlyingException=I/O error for database at /var/mobile/Applications/[omitted]. SQLite error code:266, 'not an error' errno:1}, {
* 00:04:18:25 NSFilePath = "/var/mobile/Applications/[omitted].sqlite";
* 00:04:18:25 NSPOSIXErrorDomain = 1;
* 00:04:18:25 NSSQLiteErrorDomain = 266;
* 00:04:18:25 NSUnderlyingException = "I/O error for database at /var/mobile/Applications/[omitted].sqlite. SQLite error code:266, 'not an error' errno:1";
* 00:04:18:25 }
編集
コアデータ関連のコードは次のとおりです (ほとんどが標準のボイラープレートです)。
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
//managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
// See http://iphonedevelopment.blogspot.com.au/2009/09/core-data-migration-problems.html
NSString *path = [[NSBundle mainBundle] pathForResource:@"modelDB" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSString *storePath = [[Utils documentsDirectory] stringByAppendingPathComponent: @"modelDB.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath: storePath];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// Allow inferred migration from the original version of the application.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle the error.
CLS_LOG(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
//Turn on complete file protection (encrypts files when phone is locked using device pin)
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if(![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storePath error:&error])
{
//handle error
}
return persistentStoreCoordinator;
}
ユーザーがログアウトすると、これが呼び出されてモデル ストアが削除されます。
- (NSPersistentStoreCoordinator *)resetPersistentStore
{
NSError *error = nil;
if ([persistentStoreCoordinator persistentStores] == nil)
return [self persistentStoreCoordinator];
[managedObjectContext release];
managedObjectContext = nil;
//If there are many stores, this could be an issue
NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] lastObject];
if (![persistentStoreCoordinator removePersistentStore:store error:&error])
{
CLS_LOG(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// Delete file
if ([[NSFileManager defaultManager] fileExistsAtPath:store.URL.path]) {
if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error])
{
CLS_LOG(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
// Delete the reference to non-existing store
[persistentStoreCoordinator release];
persistentStoreCoordinator = nil;
NSPersistentStoreCoordinator *r = [self persistentStoreCoordinator];
return r;
}
私のアプリにはストアが 1 つしかないため、問題は発生しないと思いますNSPersistentStore *store = [[persistentStoreCoordinator persistentStores] lastObject];
。