SwiftUI中WKWebView无法通过JS fetch加载本地文件的解决需求
解决WKWebView中本地HTML fetch相对路径文件的问题
问题情况
将本地HTML文件加载到SwiftUI的WKWebView中时,HTML内的fetch("/somefolder/model.txt")无法识别应用的完整文件路径,导致请求失败。但手动构造完整URL在Safari移动端浏览器中可正常访问该文件。
问题原因
- 访问权限范围限制:当前代码中
loadFileURL的allowingReadAccessTo参数设置为index.html文件的URL,这意味着WebView仅能访问该文件所在的目录,无法访问其他目录下的文件。 - 重复加载请求冲突:
updateUIView中同时调用了loadFileURL和load(request),这会导致WebView加载逻辑混乱,优先使用普通的load(request)而不是带访问权限的loadFileURL。 - 相对路径不匹配:HTML中使用的根路径
/somefolder不符合bundle内的文件结构,bundle中的文件路径是相对根目录的,而非系统根路径。
解决方案
1. 调整WKWebView的加载逻辑和访问权限
修改updateUIView方法,将allowingReadAccessTo设置为bundle的根目录,同时移除重复的load(request)调用:
struct SwiftUIWebview: UIViewRepresentable{ func makeUIView(context: Context) -> WKWebView { let prefs = WKWebpagePreferences() prefs.allowsContentJavaScript = true let config = WKWebViewConfiguration() config.defaultWebpagePreferences = prefs config.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") let browser = WKWebView(frame: .zero, configuration: config) return browser } func updateUIView(_ uiView: WKWebView, context: Context) { guard let indexURL = Bundle.main.url(forResource: "index", withExtension: "html"), let bundleRoot = Bundle.main.resourceURL else { return } // 仅使用loadFileURL,设置访问权限为bundle根目录 uiView.loadFileURL(indexURL, allowingReadAccessTo: bundleRoot) } } struct ContentView: View { var body: some View { VStack { SwiftUIWebview() } } }
2. 修正HTML中的相对路径
根据bundle内的实际文件结构调整fetch的路径:
- 如果
somefolder和index.html在同一层级,使用相对路径:
<script> // 相对路径,从index.html所在目录出发 const url = "./somefolder/model.txt" fetch(url) .then(r => r.text()) .then(t => console.log(t)) </script>
- 如果
somefolder是bundle根目录下的子目录,也可以使用绝对路径(基于bundle根目录):
<script> // 基于bundle根的绝对路径 const url = "somefolder/model.txt" fetch(url) .then(r => r.text()) .then(t => console.log(t)) </script>
3. 验证文件的Bundle配置
确保model.txt和somefolder已正确添加到Xcode项目中,并且在Target Membership中勾选了对应的应用目标,保证文件被打包到bundle内。
内容的提问来源于stack exchange,提问作者Sayan Pandey
相关产品推荐
相关产品推荐

