天天看点

数据库加密之Xcode9.0后,sqlcipher加密:Implicit declaration of function ’sqlite3_key‘is invalid in C99问题

问题背景

Xcode由8.3.3升级到9.0,原先在Xcode8.3.3能编译并运行成功的项目,在Xcode9.0编译失败,出现如下错误:

在FMDatabase.m中:

数据库加密之Xcode9.0后,sqlcipher加密:Implicit declaration of function ’sqlite3_key‘is invalid in C99问题
数据库加密之Xcode9.0后,sqlcipher加密:Implicit declaration of function ’sqlite3_key‘is invalid in C99问题

前一篇文章讲到sqlcipher数据库加密的配置教程是没有问题的,问题在于Implicit declaration of funciton,字面意思叫隐式声明,我们理解为,在当前文件FMDatabase.m以及它内部#import的文件中,只找到了function的实现,并没有找到头文件和其声明。这是升级Xcode9.0后,C99编译环境导致的。

问题排查

我们可以将这归为一类问题,Implicit declaration of funciton ‘xxx’ is invalid in C99,这类问题的解决办法一般是:

  1. 找到这个‘xxx’方法被调用的**.m文件
    这里sqlite3_key和sqlite3_rekey是在FMDatabase.m文件中使用
  2. 在**.m中找到‘xxx’是引用自哪一个文件
    这里sqlite3_key和sqlite3_rekey的声明源自#import < sqlite3.h >
  3. 确定‘xxx’方法在这个文件中已经被正确声明

    这里sqlite3.h文件存在sqlite3_key和sqlite3_rekey的声明确实存在于sqlcipher/Source/目录下,

    但是#import < sqlite3.h >显然无法正确链接到该位置,

    按住‘command’,用鼠标点击#import < sqlite3.h > ,Jump to defination,

    发现#import < sqlite3.h >链接到了iOS11.0/usr/include/sqlite3.h文件下,而该文件中不存在sqlite3_key和sqlite3_rekey的声明。

    至此,我们就找到隐式声明的问题所在了。

解决办法

修改链接路径,使其引用自正确的文件

以本文的问题为例,既然是链接文件出错,那么我们通过修改#import < sqlite3.h > 改为#import < SQLCipher/sqlite3.h > ,让其链接到sqlcipher下的sqlite3.h文件,可以解决这个问题

注意,如果像我们上一篇文章,是通过静态库来配置SQLCipher,是找不到< SQLCipher/sqlite3.h>路径的,我们可以通过强制打破隐式声明的方式解决这个问题,在FMDatabase.m中声明sqlite3_key和sqlite3_rekey:

#if defined(SQLITE_HAS_CODEC)
SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey);
SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey);
#endif