WKSchemeHandler 是 iOS 11 之后在 WebKit 中引入的一个协议,用于处理自定义 URL scheme 的网络请求。这对于需要加载非 HTTP 或 HTTPS 协议的资源(比如自定义的本地资源)非常有用。下面是它的常见用法:

1. 基本原理

WKSchemeHandler 允许我们在 WKWebView 加载指定的自定义 scheme URL 时拦截请求,并可以在代码中生成响应内容。要使用 WKSchemeHandler,首先需要创建一个实现了 WKURLSchemeHandler 协议的类,并实现其中的两个方法:

  • startURLSchemeTask(_:):用于开始处理请求。
  • stopURLSchemeTask(_:):用于取消请求。

2. 使用步骤

Step 1:创建自定义的 WKURLSchemeHandler 实现

首先,新建一个类并实现 WKURLSchemeHandler 协议。

import WebKit

class CustomSchemeHandler: NSObject, WKURLSchemeHandler {
    func start(_ urlSchemeTask: WKURLSchemeTask) {
        guard let url = urlSchemeTask.request.url else { return }

        // 这里可以根据 URL 做处理,返回相应的数据
        if url.scheme == "custom" {
            // 假设加载的是本地图片
            let imagePath = Bundle.main.path(forResource: "sample", ofType: "png")
            let data = try? Data(contentsOf: URL(fileURLWithPath: imagePath!))

            // 构建响应
            let response = URLResponse(url: url, mimeType: "image/png", expectedContentLength: data!.count, textEncodingName: nil)
            urlSchemeTask.didReceive(response)
            urlSchemeTask.didReceive(data!)
            urlSchemeTask.didFinish()
        }
    }

    func stop(_ urlSchemeTask: WKURLSchemeTask) {
        // 处理请求取消情况
    }
}

Step 2:注册自定义的 Scheme

然后,在 WKWebViewConfiguration 中注册该自定义 scheme 和 WKURLSchemeHandler

let webViewConfig = WKWebViewConfiguration()
let schemeHandler = CustomSchemeHandler()

// 注册自定义 scheme,比如 "custom"。
webViewConfig.setURLSchemeHandler(schemeHandler, forURLScheme: "custom")

let webView = WKWebView(frame: .zero, configuration: webViewConfig)

Step 3:加载自定义 Scheme 的 URL

在创建好 WKWebView 后,可以加载使用该自定义 scheme 的 URL,例如:

if let url = URL(string: "custom://sample.png") {
    webView.load(URLRequest(url: url))
}

3. 常见应用场景

  • 本地资源加载:加载 app 中的图片、音频等资源,而不需要在 WKWebViewfile:// 协议访问本地文件。
  • 自定义内容响应:可以根据 URL 的不同路径,动态生成并返回自定义内容,比如特定的数据或 HTML 文件。
  • 网络资源拦截:对自定义的 scheme 请求进行拦截处理,甚至可以做额外的安全检查或内容预处理。

4. 注意事项

  • WKURLSchemeHandler 仅支持自定义的 scheme,不支持 httphttps
  • 必须在 WKWebView 配置创建后,且在加载页面前注册自定义的 scheme。
  • 自定义的 scheme 通常应避免与已有的标准 URL scheme 冲突,比如 mailtotel 等。

通过以上步骤,我们就可以使用 WKSchemeHandler 来定制和拦截 WKWebView 中的网络请求,满足自定义内容加载的需求。