天天看點

資料庫加密之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