您的位置:

SwiftWKWebView详细阐述

一、WKWebView概述

WKWebView是一个在iOS8及以上版本中推出的基于WebKit引擎的Web视图控件,它可以显示网页,并且支持网页交互。它是在UIWebView的基础上进行了大量改进,比如提高了渲染速度、内存占用更小、JavaScript执行速度更快、支持了WebKit的新特性等。WKWebView主要提供了以下功能:

1、加载Web页面,并且支持显示HTML、CSS、JavaScript等网页内容;

2、通过JavaScript交互,实现Web页面与原生代码的双向通信;

3、可以进行缩放、前进、后退、刷新等基本的Web导航操作;

4、可以显示PDF、图片等非HTML格式的内容。

二、WKWebView常用操作

1、加载网页

    if let url = URL(string: "https://www.example.com") {
        let request = URLRequest(url: url)
        webView.load(request)
    }

使用URL初始化一个URLRequest对象,然后通过load函数将URLRequest传入WebView中,即可加载网页。

2、JavaScript交互

// 将函数注入到JavaScript环境中
webView.configuration.userContentController.add(self, name: "myFunction")
    
// 在加载完成的代理方法中注入JavaScript代码
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    let js = "function myFunction() { /*代码实现*/ }"
    webView.evaluateJavaScript(js, completionHandler: nil)
}

// 通过JavaScript调用原生代码
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "myFunction" {
        //获取传入的参数
        if let dict = message.body as? [String:Any] {
           //处理数据
        }
    }
}

使用add函数将原生代码中的函数名注入到JavaScript环境中,然后在加载完成的代理方法中通过evaluateJavaScript函数将JavaScript代码注入到WebView中,在JavaScript中可以通过window.webkit.messageHandlers.myFunction.postMessage()调用原生代码中的函数。

3、前进、后退、刷新

// 前进
webView.goForward()

// 后退
webView.goBack()
    
// 刷新
webView.reload()

使用goForward、goBack、reload函数即可进行基本的导航操作。

三、WKWebView高级操作

1、JavaScript与原生数据交互

// 在JS中调用window.webkit.messageHandlers.getData.postMessage("parameter");
let config = WKWebViewConfiguration()
let userContentController = WKUserContentController()
let script = WKUserScript(source: "window.webkit.messageHandlers.getData.postMessage('parameter');", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
userContentController.add(self, name: "getData")
userContentController.addUserScript(script)
config.userContentController = userContentController
let webView = WKWebView(frame: .zero, configuration: config)
    
// 在原生代码中处理数据
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "getData" {
        //获取传入的参数
        if let dict = message.body as? [String:Any] {
            //处理数据
            let parameter = dict["parameter"] as? String
            // 返回数据
            let javascript = "yourFunction('\(result)')"
            webView.evaluateJavaScript(javascript, completionHandler: nil)
        }
    }
}

在JS中调用window.webkit.messageHandlers.方法名.postMessage('参数')来触发原生代码中的方法,原生代码中通过WKScriptMessage的body属性来获取传入的参数,处理数据后通过evaluateJavaScript函数返回数据。

2、WebView截图

webView.takeSnapshot(with: nil) { (image, error) in
    if let snapshotImage = image {
        //处理截图
    }
}

使用takeSnapshot函数进行WebView截图操作,通过回调函数获取截取到的图片,可以进行后续的处理。

3、网页离线缓存

let url = URL(string: "https://www.example.com")
let config = WKWebViewConfiguration()
let cachePath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0]
let fullPath = cachePath + "/myCache"
let cache = URLCache(memoryCapacity: 4 * 1024 * 1024, diskCapacity: 20 * 1024 * 1024, diskPath: fullPath)
config.urlCache = cache
if let webView = WKWebView(frame: self.view.bounds, configuration: config) {
    let request = URLRequest(url: url!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 15.0)
    webView.load(request)
    view.addSubview(webView)
}

使用URLCache可以实现网页离线缓存,提高用户的浏览体验。可以通过设置URLCache的memoryCapacity(内存缓存大小)、diskCapacity(磁盘缓存大小)等属性来控制缓存的大小。在加载网页时,使用URLRequest的cachePolicy属性来设置缓存策略。

四、WKWebView问题处理

1、WebKit内存泄露

在长时间运行的情况下,WKWebView可能会产生内存泄露的问题,一些资源无法释放,导致内存占用越来越高。这时可以通过手动释放资源,以及设置缓存大小等方式来减少内存泄露的风险。

2、JavaScript交互问题

在进行JavaScript交互时,容易出现数据传输错误、JS环境没加载完就调用函数等问题。可以通过设置WKUserContentController的scriptMessageHandler属性来避免出现这些问题。

3、WKWebView加载失败

在加载过程中,可能会出现因为网络等原因导致WebView无法加载页面的问题。可以通过设置config对象的preferences属性的minimumFontSize等属性、request对象的timeoutInterval等属性来提高网页加载成功率。

五、总结

通过以上的阐述,我们可以看到WKWebView是一个功能强大的Web控件。它具备良好的交互性能、高效的渲染速度、完善的JavaScript支持等特点,可以满足多种场景的需求。在使用过程中,需注意处理内存泄露、合理设置缓存、处理好JS交互等问题,以达到更好的用户体验。