由于NSSQLiteErrorDomain=1032,iOS核心数据保存上下文方法不成功

由于NSSQLiteErrorDomain=1032,iOS核心数据保存上下文方法不成功,ios,objective-c,sqlite,core-data,concurrency,Ios,Objective C,Sqlite,Core Data,Concurrency,关于这个问题的一些背景,我试图包括我认为可能有助于理解上下文的相关内容 我目前正在添加一个链接库,该库使用核心数据保存一些用户信息,并添加一个功能,将实体添加到应用程序中已经存在的核心数据模型中。每个managedObjectContext在创建(验证)时都有自己的实例以及自己的PSC和MOM,它们都不与其他实体交互(因此看起来是独立的) 以下所有代码、错误和(我相信问题)都是应用程序的主要目标。(希望不是新添加的链接库。 saveContext方法是: - (void)saveContext

关于这个问题的一些背景,我试图包括我认为可能有助于理解上下文的相关内容

我目前正在添加一个链接库,该库使用核心数据保存一些用户信息,并添加一个功能,将实体添加到应用程序中已经存在的核心数据模型中。每个managedObjectContext在创建(验证)时都有自己的实例以及自己的PSC和MOM,它们都不与其他实体交互(因此看起来是独立的)

以下所有代码、错误和(我相信问题)都是应用程序的主要目标。(希望不是新添加的链接库。

saveContext方法是:

- (void)saveContext {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSError *error = nil;
        // Register
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myManagedObjectContextDidSaveNotificationHandler:) name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext];

        if (self.managedObjectContext != nil) {
            if ([self.managedObjectContext hasChanges]) {
                BOOL success = [self.managedObjectContext save:&error];
                if (!success) {
                    [Error showErrorByAppendingString:NSLocalizedString(@"UnableToSaveChanges", nil) withError:error];
                } else {
                     // 
                }
            }
        }
        // Unregister
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification    object:self.managedObjectContext];
    });  
}
调用时,error=nil,success=NO,通过强制编译器通过异常,我得到以下结果:

CoreData:错误:获取PermenantIsForbjects期间出现异常:更新max pk失败:尝试写入userInfo为{NSSQLiteErrorDomain=1032的只读数据库; }

我在谷歌上搜索过“NSSQLiteErrorDomain=1032”、“获取PermenantisForbjects”和“CoreData只读数据库”。看起来每个对象的主键都是相同的,但我正在设置这个值,我相信sqlite是一样的。我还没有找到任何解决办法来帮助解决这个问题。我确实在启动时传递了参数,“并发调试1”设置为on

我还没有实现GetainPermenantisProjects,我搜索了整个项目,找不到它的实现,所以我认为CoreData正在使用它

saveContext方法是在主队列上调用的,因为我的前辈就是这样编写代码的,我现在没有时间处理它

调用saveContext的方法(从后台线程):


NSSQLiteErrorDomain
键表示此错误来自SQLite,核心数据正在将其传回给您:

SQLITE_READONLY_DBMOVED错误代码是SQLITE_READONLY的扩展错误代码。SQLITE_READONLY_DBMOVED错误代码表示无法修改数据库,因为数据库文件在打开后已被移动,因此,如果进程因回滚日志命名不正确而崩溃,则任何修改数据库的尝试都可能导致数据库损坏

…这似乎意味着SQLite正在使持久存储文件成为只读文件,因为自从它被打开以来发生了一些事情,SQLite正在尝试防止数据损坏

我没有看到你发布的代码中有任何明显的错误,至少就错误代码描述而言。因此,我想知道,您是否在其他任何地方做了任何会直接影响持久存储文件的事情(即以任何方式触摸文件,而不是通过核心数据获取/保存调用)


错误代码描述中提到的回滚日志使我怀疑将
journal\u mode
设置为
TRUNCATE
是否相关。如果是我,我会删除它(我不知道它在这里要实现什么),或者将它设置为
DELETE
。至少出于测试目的,希望能够更好地理解问题。

您是如何创建持久存储的,SQLite文件位于何处?@Wain更新了问题,并给出了对您问题的回答。希望这能让事情更清楚。汤姆,谢谢!因此,正是将日志模式设置为“删除”解决了这个问题。我删除了您回答后的选项,这似乎解决了问题,但当时,我添加到DB中的新实体只有在我保存功能之前存在于MOM中的实体时才会持续存在。我以为这个问题已经解决了,我正在做其他的事情,但是今天我添加了这个选项,并将其设置为删除,似乎就这样做了。谢谢现在来研究一下为什么。。。
- (NSMutableArray *)convertRawStepDataTo:(NSMutableArray*)steps
                           withDates:(NSMutableArray*)dates
              inManagedObjectContext:(NSManagedObjectContext*)theMOC {

    NSMutableArray *theStepsArray = [[NSMutableArray alloc] init];

    // prepare values for chart
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    StepSelector *theSelector = [[StepSelector alloc] init];
    NSString* apiSelectionForStep = [theSelector getCurrentSelectionString];

    for (int iter = 0; iter < steps.count; iter++) {
        NSNumber *currStepValue = [steps objectAtIndex:iter];
        // NSNumber *stepCountforIter = [NSNumber numberWithLong:[[steps objectAtIndex:iter] longValue]];

        NSNumber* dateForIter = [NSNumber numberWithLong:[[dates objectAtIndex:iter] longLongValue]];
        Step *step = [delegate addStepObjectToPersistentStorewithAPI:apiSelectionForStep
                                                         andStep:stepCountforIter
                                                         andDate:dateForIter
                                                          forMOC:theMOC];

        [theStepsArray addObject:step];

        if (VERBOSE) {
            NSLog(@"This is step number %d, with object ID: %@", count, [theMOC objectWithID:step.objectID]);
            count++;
        }
    }
    [delegate saveContext];
    return theStepsArray;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [self getStoreURL];

    // Rollback journalling mode...
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption,
                             NSFileProtectionComplete, NSFileProtectionKey,
                             @{@"journal_mode": @"TRUNCATE"}, NSSQLitePragmasOption, nil];

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    NSError *error = nil;
    self.persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error];
    if (!self.persistentStore) {
        NSLog(@"Error: %@",error);
        [Error showErrorByAppendingString:NSLocalizedString(@"UnableToFindDatabaseFile", nil) withError:error];
    }

    return persistentStoreCoordinator;
}

-(NSURL *)getStoreURL {
    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kSQLFILENAME];
    /*
     Set up the store.
     For the sake of illustration, provide a pre-populated default store.
     */
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // If the expected store doesn't exist, copy the default store.
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:SQLFILEPATHRESOURCE ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];

    return storeUrl;
}