这几天写了一个粤小词词典应用,打算做个离线版的,于是使用了自己的 sqliteDB 文件。
Android 上一切正常,Expo Go 调试正常,一到 eas build iOS 就文件不是数据库文件。
如果直接解析 DB 后缀的是没法使用的,更改一下 Metro 的配置,支持 db 文件,也可以项目使用其他的。
`
const { getDefaultConfig } = require('expo/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
defaultConfig.resolver.assetExts.push('db');
module.exports = defaultConfig;
改完后,执行清理缓存的启动:
expo start -c
然后使用以下写法:
`
async function openDatabase(pathToDatabaseFile: string): Promise<SQLite.WebSQLDatabase> {
if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
}
await FileSystem.downloadAsync(
Asset.fromModule(require(pathToDatabaseFile)).uri,
FileSystem.documentDirectory + 'SQLite/myDatabaseName.db'
);
return SQLite.openDatabase('myDatabaseName.db');
}
可以看到从资源文件里面解析出来 db 后,下载到本机(这里说一下:使用 expo 托管流的,会将资源文件托管到亚马逊的 CDN 上,在应用首次启动会下载下来)。
回到 iOS 真机上来,我使用模拟器,打开了模拟器的本地存储,发现实际上是有数据库文件的,但是似乎大小不正常,我的 DB 有 3m,但是模拟器上下载下来的只有 200kb,应该是下载的时候损坏了。所以导致不是一个 db 文件。于是我换了一下写法,使用了 copy 函数,从资源文件复制到本机,结果打包后还是不行,直接没有复制。
后来去官方论坛查看,非常多的人遇到自带 db 文件无法使用的问题,并且几乎没有官方人员解答,都是最后被关闭话题。其中一个是:使用 hook,来监听文件下载完成后执行其他操作。这样可以避免下载问题导致的文件损坏,鉴于下载问题,我修改了一些逻辑,改成了不托管 db 文件,然后启动项目后从自带资源文件里复制。
`
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHideAsync().catch((e) => console.log(e));
const getDatabase = async (databaseAsset: Asset) => {
try {
if (!(await FileSystem.getInfoAsync(sqlDir)).exists) {
await FileSystem.makeDirectoryAsync(sqlDir);
}
await FileSystem.copyAsync({
//@ts-ignore
from: databaseAsset.localUri,
to: sqlDir + '/' + databaseName,
});
return SQLite.openDatabase(databaseName);
} catch (err) { /* Handle error */
}
};
if (assets && assets[0] && !assetsError) {
const databaseAsset = assets[0];
// @ts-ignore
ZenStore.db = await getDatabase(databaseAsset);
}
} catch (e) {
// We might want to provide this error information to an error reporting service
console.warn(e);
alert(e.message);
console.error(e)
} finally {
setLoadingComplete(true);
SplashScreen.hideAsync();
}
}
loadResourcesAndDataAsync();
}, [assets]);
修改托管配置:app.json ,将 db 排除在外,因为我只托管图片所以将默认的*换成下面的就好了。
`
"assetBundlePatterns": [
"assets/images/*"
],
希望能帮助到遇到这个问题的小伙伴。
另外粤小词语 iOS 上线啦:粤小词 Apple Store
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于