【问题标题】:SQLCipher and CoreData issue: CoreData could not fulfill a fault forSQLCipher 和 CoreData 问题:CoreData 无法完成故障
【发布时间】:2015-02-03 09:56:02
【问题描述】:

我对 SQLCipher db 加密和 CoreData 有疑问: 当我将持久存储协调器与 SQLCipher 一起使用时,它总是在第一次重新启动应用程序后因错误的一对多关系而崩溃。 因此,当我第一次启动应用程序时,我创建了具有关系的 NSManagedObjects,然后,当我保存数据库并重新打开应用程序时,当我尝试访问这些关系时它会崩溃。 没有 SQLCipher 一切正常。

这是 SQLCipher 持久存储初始化的代码:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (!_persistentStoreCoordinator) {
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"];
        NSDictionary *options = @{EncryptedStorePassphraseKey: @"MyApp",
                                                            EncryptedStoreDatabaseLocation: storeURL};
        NSError *error;
        _persistentStoreCoordinator = [EncryptedStore makeStoreWithOptions:options managedObjectModel:[self managedObjectModel] error:&error];
        if (error) {
            NSLog(@"%@", error);
        }
    }

    return _persistentStoreCoordinator;
}

我创建 NSManagedObject 的代码:

- (id)createObjectWithClassName:(NSString *)name
{
    NSManagedObject *object = [[NSClassFromString(name) alloc] initWithEntity:[NSEntityDescription entityForName:name inManagedObjectContext:self.context] insertIntoManagedObjectContext:self.context];
    return object;
}

【问题讨论】:

  • 创建托管对象的代码是什么样的?
  • @TomHarrington 我用 NSManagedObject 创建代码更新了帖子
  • 您是否尝试运行任何迁移,或者您是否在保存数据库和重新打开应用程序之间对托管对象模型进行了任何更改?
  • 我已经实现了这样的保护,但是客户想使用 SQLCipher...

标签: ios objective-c core-data sqlcipher


【解决方案1】:

使用 SQLCipher 确保您拥有全新的 SQLite 数据库。在数据库由于某种原因已经有数据的情况下尝试使用密钥对数据库进行编译指示只是尝试对其进行解密。

ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'secret'; -- create a new encrypted database
CREATE TABLE encrypted.t1(a,b); -- recreate the schema in the new database (you can inspect all    objects using SELECT * FROM sqlite_master)
INSERT INTO encrypted.t1 SELECT * FROM t1; -- copy data from the existing tables to the new tables in the encrypted database
DETACH DATABASE encrypted;

--

//For persistentStoreCoordinator:
// Give modelName = @"MyApp.sqlite";
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator:(NSString*)modelName
{
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }


    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    @"PushNoticationModal.sqlite"
    NSURL *storeUrl = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:modelName]];
    NSError *error = nil;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    NSError *error;
    persistentStoreCoordinator = [EncryptedStore makeStoreWithOptions:options managedObjectModel:[self managedObjectModel] error:&error];
    if (error) {
    NSLog(@"%@", error);
    }

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        NSLog(@"persistentStoreCoordinator Error: %@,%@",error,[error userInfo]);
    }



    return persistentStoreCoordinator;
}

【讨论】:

  • 您的代码对我没有帮助。而且它还有一个逻辑问题:你创建了两次persistentStoreCoordinator(正常和加密),这没有任何意义......
  • 上次有一些错误,我纠正了,但由于时间不足,我已经通过bot测试了。
【解决方案2】:

终于我自己找到了答案。

我调查了不同的案例,发现这个问题只发生在我的数据模型中。

问题是我在 NSManagedObject 类中有一个名为“index”的属性。

看起来 SQLCipher 在内部使用了这样的属性,并且与它发生了冲突。 一旦我将其重命名为另一个名称,一切正常!

【讨论】:

    猜你喜欢
    • 2011-08-01
    • 2012-08-07
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多