You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 06:50:24