您还可以将自定义 URL 方案处理程序添加到 WKWebView 并在您的网页中使用该方案。然后,此自定义方案处理程序可以从任意位置加载数据。需要注意的是,这会将整个文件加载到内存中,因此它不适用于大文件。
let configuration = WKWebViewConfiguration()
configuration.setURLSchemeHandler(MySchemeHandler(), forURLScheme: "MyScheme")
let webView = WKWebView(frame: .zero, configuration: configuration)
您的 MySchemeHandler 需要实现 webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) 和 webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask)(尽管后者可以为空)。然后,将自定义 URL 转换为文件 URL 并加载文件。
加载文件似乎很痛苦。可能有更好的方法,但这是我们使用的:
URLSession.shared.dataTask(with: fileUrl) { data, response, error in
if error != nil {
// cancel
return
}
let taskResponse: URLResponse
if #available(iOS 13, *) {
taskResponse = HTTPURLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
} else {
// The HTTPURLResponse object created above using the URLResponse constructor crashes when sent to
// urlSchemeTask.didReceive below in iOS 12. I have no idea why that is, but it DOESN'T crash if we
// instead use the HTTPURLResponse-only constructor. Similarly, it doesn't crash if we create a
// URLResponse object instead of an HTTPURLResponse object. So, if we know the mimeType, construct an
// HTTPURLResponse using the HTTPURLResponse constructor, and add the appropriate header field for that
// mime type. If we don't know the mime type, construct a URLResponse instead.
if let mimeType = response?.mimeType {
// The imodeljs code that loads approximateTerrainHeights.json requires the HTTP Content-Type header
// to be present and accurate. URLResponse doesn't have any headers. I have no idea how the
// HTTPURLResponse contstructor could fail, but just in case it does, we fall back to the
// URLResponse object.
taskResponse = HTTPURLResponse(url: urlSchemeTask.request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Content-Type": "\(mimeType); charset=UTF-8"]) ?? URLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
} else {
taskResponse = URLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
}
}
urlSchemeTask.didReceive(taskResponse)
urlSchemeTask.didReceive(data!)
urlSchemeTask.didFinish()
}.resume()