FMDB数据库加密问题---数据不显示

参考文章:https://www.jianshu.com/p/a849bf4858ad
本问题是直接对数据库加密产生的问题

问题: 从未加密得数据库升级到加密数据库,则需要考虑到兼容问题
方案: 打开数据库open -> 设置秘钥 setkey -> 查看连接 goodConnection -> 新建数据库并迁移数据

代码

- (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
#if SQLITE_VERSION_NUMBER >= 3005000
    if (_db) {
        return YES;
    }
    
    int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]);
    if(err != SQLITE_OK) {
        NSLog(@"error opening!: %d", err);
        return NO;
    } else {
        [self setKey:DB_KEY];
    }
    
    if (![self goodConnection]) {
        if ([NSString stringWithCString:[self sqlitePath] encoding:NSUTF8StringEncoding]) {
            [self upgradeDatabase:[NSString stringWithCString:[self sqlitePath] encoding:NSUTF8StringEncoding]];
// 下面几行是重点,很多不细心得程序员总是喜欢拷贝别人的文章粘贴成自己的博客,真是害人。
// 原因:原本是未加密得数据库,设置setKey没效果,需要迁移数据库之后再设置一次才有效
// u can try: 把下面5行隐藏了实验。从你从未加密数据库升级过来,第一次打开App总是没有数据,只有第二次打开App才会有数据显示。
            [self close];  
            BOOL reRes = [self openWithFlags:flags vfs:vfsName];
            if (reRes) {
                [self setKey:DB_KEY];
            }
        }
    }
    
    if (_maxBusyRetryTimeInterval > 0.0) {
        // set the handler
        [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
    }
    
    return YES;
#else
    NSLog(@"openWithFlags requires SQLite 3.5");
    return NO;
#endif
}

- (void)upgradeDatabase:(NSString *)path{
    NSString *targetPath = [NSString stringWithFormat:@"%@.tmp.db", path];
    if(targetPath){
        const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY '%@';", targetPath, DB_KEY] UTF8String];
        
        sqlite3 *unencrypted_DB;
        if (sqlite3_open([path UTF8String], &unencrypted_DB) == SQLITE_OK) {
            char *errmsg;
            // Attach empty encrypted database to unencrypted database
            sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, &errmsg);
            if (errmsg) {
                NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                sqlite3_close(unencrypted_DB);
            }
            
            // export database
            sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, &errmsg);
            if (errmsg) {
                NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                sqlite3_close(unencrypted_DB);
            }
            
            // Detach encrypted database
            sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, &errmsg);
            if (errmsg) {
                NSLog(@"%@", [NSString stringWithUTF8String:errmsg]);
                sqlite3_close(unencrypted_DB);
            }
            
            sqlite3_close(unencrypted_DB);
            
            //delete tmp database
            [self removeDatabasePath:targetPath targetPath:path];
        }
        else {
            sqlite3_close(unencrypted_DB);
            NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB));
        }
    }
}

- (void)removeDatabasePath:(NSString *)targetPath targetPath:(NSString *)sourcePath {
    NSFileManager *fm = [[NSFileManager alloc] init];
    [fm removeItemAtPath:sourcePath error:nil];
    [fm moveItemAtPath:targetPath toPath:sourcePath error:nil];
}

你可能感兴趣的:(FMDB数据库加密问题---数据不显示)