Подтвердить что ты не робот

Проблема SQLCipher и CoreData: CoreData не может выполнить ошибку для

У меня проблема с шифрованием SQLCipher db и CoreData: Когда я использую постоянный координатор хранилища с SQLCipher, он всегда терпит крах со связью "один ко многим" после первого перезапуска приложения. Поэтому, когда я впервые запускаю приложение, я создаю NSManagedObjects с отношениями, затем, когда я сохраняю db и снова открываю приложение, он падает, когда я пытаюсь получить доступ к этим отношениям. Без 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;
}
4b9b3361

Ответ 1

Наконец, я нахожу ответ сам.

Я исследую разные случаи и полагаю, что проблема возникает только в моей модели данных.

Проблема заключалась в том, что у меня есть одно свойство в классе NSManagedObject с именем "index".

Похоже, что SQLCipher внутренне использует такое свойство, и с ним были конфликты. Как только я переименую его на другое имя, все работает!

Ответ 2

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