1

随着我最近的应用程序更新,我在保存数据库时开始看到非常不一致的 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];不会引起问题。

4

2 回答 2

1

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

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

请注意,这会略微提高安全风险,因此您可能需要考虑在您的应用中是否有必要这样做。

于 2018-06-24T19:51:56.710 回答
0

您确定数据库每次都正确打开/关闭吗?这可能是由于文件在未正确关闭时打开而导致的问题

于 2013-05-13T09:07:41.823 回答