如何修复WKURLSchemeHandler响应中fetch与XMLHttpRequest的状态码0问题
问题描述
我需要在App中嵌入HTML5游戏(将其嵌入二进制文件,实现无网络也可运行)。使用loadHTMLString(htmlContentString, baseURL: "myschemename:///index.html")加载index.html,同时实现了WKURLSchemeHandler,但遇到异常:尽管已通过WKURLSchemeHandler返回数据,XMLHttpRequest和fetch请求仍获取到状态码"0"且response.ok为false。
现有代码
Swift 端 WKURLSchemeHandler 实现
class MyURLSchemeHandler: NSObject, WKURLSchemeHandler { func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { let fileData = ...// code that find file on disk and read it urlSchemeTask.didReceive(URLResponse( url: urlSchemeTask.request.url!, mimeType: fileURL.mimeType(), expectedContentLength: fileData.count, textEncodingName: "utf-8") ) urlSchemeTask.didReceive(fileData) urlSchemeTask.didFinish() } }
HTML 端 fetch 请求代码
<!DOCTYPE html> <html> <script> fetch("myschemename:///data.json") .then((response) => { if (response.ok) { console.log("ok"); } else { console.log("error"); } }); </script> <body> </body> </html>
解决方案
问题根源在于你创建的URLResponse对象——fetch和XMLHttpRequest对非HTTP协议的响应默认判定为失败状态(状态码0),哪怕已经返回了数据。正确的做法是改用HTTPURLResponse并设置合法的HTTP状态码(比如200):
- 替换原有
URLResponse为HTTPURLResponse,明确指定状态码为200 - 确保
Content-Type头匹配文件实际类型(比如JSON文件用application/json)
修改后的Swift代码:
class MyURLSchemeHandler: NSObject, WKURLSchemeHandler { func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { guard let fileURL = ..., // 你的文件路径获取逻辑 let fileData = try? Data(contentsOf: fileURL) else { // 文件不存在或读取失败时返回错误 urlSchemeTask.didFailWithError(NSError(domain: "MySchemeError", code: 404, userInfo: [NSLocalizedDescriptionKey: "File not found"])) return } let response = HTTPURLResponse( url: urlSchemeTask.request.url!, statusCode: 200, // 关键:设置成功状态码 httpVersion: "HTTP/1.1", headerFields: [ "Content-Type": fileURL.mimeType(), "Content-Length": "\(fileData.count)" ] )! urlSchemeTask.didReceive(response) urlSchemeTask.didReceive(fileData) urlSchemeTask.didFinish() } }
额外注意点
- 文件读取失败时,必须调用
didFailWithError返回错误,避免Web端请求长时间挂起 - 务必在
WKWebViewConfiguration中注册自定义scheme:let config = WKWebViewConfiguration() config.setURLSchemeHandler(MyURLSchemeHandler(), forURLScheme: "myschemename") let webView = WKWebView(frame: .zero, configuration: config) - 验证
fileURL.mimeType()返回的类型是否准确,错误的MIME类型可能导致Web端解析数据失败
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

