問題背景
Xcode由8.3.3更新到9.0,原先在Xcode8.3.3能編譯并運作成功的項目,在Xcode9.0編譯失敗,出現如下錯誤:
在FMDatabase.m中:
前一篇文章講到sqlcipher資料庫加密的配置教程是沒有問題的,問題在于Implicit declaration of funciton,字面意思叫隐式聲明,我們了解為,在目前檔案FMDatabase.m以及它内部#import的檔案中,隻找到了function的實作,并沒有找到頭檔案和其聲明。這是更新Xcode9.0後,C99編譯環境導緻的。
問題排查
我們可以将這歸為一類問題,Implicit declaration of funciton ‘xxx’ is invalid in C99,這類問題的解決辦法一般是:
- 找到這個‘xxx’方法被調用的**.m檔案
這裡sqlite3_key和sqlite3_rekey是在FMDatabase.m檔案中使用
- 在**.m中找到‘xxx’是引用自哪一個檔案
這裡sqlite3_key和sqlite3_rekey的聲明源自#import < sqlite3.h >
- 确定‘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