【iOS开发基础】WKWebView

WKWebView 概述

WKWebView 是 Apple 提供的现代 Web 内容渲染控件,替代了早期的 UIWebView。它基于 WebKit 框架,提供更高的性能、更低的内存占用以及更丰富的功能,适用于 iOS 和 macOS 应用。

基本用法

WKWebView 的核心功能是加载和显示网页内容。以下是一个简单的初始化示例:

import WebKit

let webView = WKWebView(frame: view.bounds)
view.addSubview(webView)

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

配置 WKWebView

可以通过 WKWebViewConfiguration 自定义行为,例如启用 JavaScript 或设置内容控制器:

let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
configuration.preferences.javaScriptEnabled = true

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

处理导航和交互

实现 WKNavigationDelegate 可以监听页面加载状态:

class ViewController: UIViewController, WKNavigationDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("页面加载完成")
    }
}

JavaScript 交互

通过 WKUserContentController 实现原生与 JavaScript 的双向通信:

configuration.userContentController.add(self, name: "nativeHandler")

// 从 JavaScript 接收消息
extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "nativeHandler" {
            print("收到 JS 消息: \(message.body)")
        }
    }
}

缓存与 Cookie 管理

使用 WKWebsiteDataStore 管理缓存和 Cookie:

let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
    for record in records {
        print("缓存记录: \(record.displayName)")
    }
}

性能优化

WKWebView 默认已优化性能,但可通过以下方式进一步调整:

  • 禁用不必要的特性(如自动播放)
  • 使用 evaluateJavaScript(_:completionHandler:) 替代频繁的 JS 调用
  • 预加载页面或资源

WKNavigationDelegate

处理网页导航相关事件,例如页面加载、重定向或错误。

// 页面开始加载时触发
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {}

// 页面加载完成时触发
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {}

// 页面加载失败时触发
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {}

// 决定是否允许导航请求(例如点击链接或提交表单)
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    decisionHandler(.allow) // 或 .cancel
}

WKUIDelegate

处理网页的 UI 相关交互,例如 JavaScript 弹窗或新窗口打开。

// 处理 JavaScript 的 alert 弹窗
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
    let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    present(alert, animated: true)
    completionHandler()
}

// 处理 JavaScript 的 confirm 弹窗
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completionHandler(false) }))
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler(true) }))
    present(alert, animated: true)
}

WKScriptMessageHandler

用于与网页中的 JavaScript 进行双向通信。

// 注册消息处理器
let userContentController = WKUserContentController()
userContentController.add(self, name: "nativeHandler")

// 接收来自 JavaScript 的消息
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "nativeHandler" {
        print("Received message: \(message.body)")
    }
}

注意事项

  • WKWebView 与 UIWebView 的 API 不兼容
  • 跨域请求限制更严格,需服务器配合 CORS
  • 部分旧版 HTML5 特性可能不支持
  • 内存管理:WKWebView 的 delegate 需避免循环引用,建议使用 weak 引用。
  • 线程安全:WKWebView 的回调方法可能在非主线程执行,UI 操作需切换到主线程。
  • HTTP 认证:通过 didReceive challenge 方法处理 HTTPS 认证请求。
// HTTPS 认证处理
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
        let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        completionHandler(.useCredential, credential)
    }
}

 WebKit源码链接 GitHub - WebKit/WebKit: Home of the WebKit project, the browser engine used by Safari, Mail, App Store and many other applications on macOS, iOS and Linux.

本demo是WKWebView的基本使用和交互 ,实现了原生调用js的方法、js调用原生的方法、通过拦截进行交互的方法;修改内容 加入沙盒 / /加载沙盒 不带参数 // NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // NSString * path = [paths objectAtIndex:0]; // path = [path stringByAppendingString:[NSString stringWithFormat:@"/app/html/index.html"]]; // NSURL *url = [NSURL URLWithString:[[NSString stringWithFormat:@"file://%@",path] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL:[NSURL fileURLWithPath:NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject]]; // [self.wkView loadFileURL:url allowingReadAccessToURL:[NSURL fileURLWithPath: [paths objectAtIndex:0]]]; // 带参数 /* NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * path = [paths objectAtIndex:0]; path = [path stringByAppendingString:[NSString stringWithFormat:@"/app/html/index.html"]]; NSURL * url = [NSURL fileURLWithPath:path isDirectory:NO]; NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; [queryItemArray addObject:[NSURLQueryItem queryItemWithName:@"version" value:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]]]; [urlComponents setQueryItems:queryItemArray]; [self.wkView loadFileURL:urlComponents.URL allowingReadAccessToURL:[NSURL fileURLWithPath: [paths objectAtIndex:0]]]; */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值