CoreData DB上的SQLite错误266

时间:2013-05-07 18:23:13

标签: ios sqlite core-data

通过我最近的应用更新,我在保存数据库时已经开始看到非常不一致的SQLite错误。这些都发生在多个用户身上,因此不只是同一个用户反复崩溃(尽管多次发生在同一个用户身上)。我收到错误266,即SQLITE_IOERR_READ。我没有发现其他人遇到这个错误,所以不知道为什么我会得到它。

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;
}

我的应用只有一个商店,因此我认为NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] lastObject];不会导致问题。

2 个答案:

答案 0 :(得分:0)

来得晚了一点,但我注意到这个错误几乎总是在我们的应用程序被推到后台时发生的。

在创建persistentStoreCoordinator时,您可能需要将NSPersistentStoreFileProtectionKey选项设置为NSFileProtectionCompleteUntilFirstUserAuthentication,而不是NSFileProtectionComplete

请注意,这会稍微增加安全风险,因此您可能需要考虑在应用程序中是否有必要。

答案 1 :(得分:-1)

您确定每次都正确打开/关闭数据库吗?由于文件在未正确关闭时打开,因此可能会出现问题