WKWebView 使用全解

常见的使用方法和功能

  1. 前进和后退:
webView.goBack() // 后退
webView.goForward() // 前进
  1. 刷新页面:
webView.reload()
  1. 监听页面加载事件:
extension ViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("页面加载完成")
    }
}
  1. 在 WebView 中执行 JavaScript:
webView.evaluateJavaScript("document.getElementById('myElement').innerHTML") { (result, error) in
    if let html = result as? String {
        print(html)
    }
}
  1. 在 WebView 中注入自定义 JavaScript:
let script = WKUserScript(source: "alert('Hello world!');", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let userContentController = webView.configuration.userContentController
userContentController.addUserScript(script)
  1. 与 WebView 进行交互:
    使用 WKUserContentController 对象处理 WebViewJavaScript 之间的消息交互。首先,为 WKWebViewConfiguration 实例创建一个 userContentController 对象,然后通过 add 方法添加消息处理器。
let userContentController = webView.configuration.userContentController
userContentController.add(self, name: "myMessageHandler")

然后,在 JavaScript 中,使用 window.webkit.messageHandlers.myMessageHandler.postMessage() 将消息发送到 WebView。

  1. 清除缓存:
let websiteDataTypes = NSSet(array: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
let date = Date(timeIntervalSince1970: 0)
WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes as! Set<String>, modifiedSince: date) {
    print("缓存已清除")
}
  1. 在 WebView 中注入自定义 JavaScript:
let script = WKUserScript(source: "alert('Hello world!');", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let userContentController = webView.configuration.userContentController
userContentController.addUserScript(script)

WKWebViewConfiguration 使用方法和功能

WKWebViewConfiguration 是用于配置 WKWebView 的类。它可以用于控制如何显示 WebView 中的内容、JavaScript 的交互、缓存和 Cookie 管理等方面。下面是一些常用的 WKWebViewConfiguration 属性:

  1. processPool: 使用 WKProcessPool 实例作为 WebView 进程池,多个 WKWebView 可以共享一个 WKProcessPool 实例,从而实现在同一进程中运行多个 WebView

  2. userContentController: 使用 WKUserContentController 实例来管理 WebView 中的 JavaScript 消息处理和用户脚本。

  3. preferences: 使用 WKPreferences 实例来控制 WebView 的偏好设置,例如 JavaScript 是否启用、内置字体是否可缩放、文本是否自动适应用户选择等。

  4. websiteDataStore: 使用 WKWebsiteDataStore 实例来管理 WebView 中的网站数据,例如缓存、Cookie、本地存储等。

  5. allowsInlineMediaPlayback: 布尔值,指定是否允许媒体以内联模式播放。

  6. mediaTypesRequiringUserActionForPlayback: WKAudiovisualMediaTypes 枚举,指定哪些媒体类型需要用户手动触发播放。

  7. dataDetectorTypes: WKDataDetectorTypes 枚举,指定 WebView 中自动检测链接的类型。

创建 WKWebViewConfiguration 实例:

let configuration = WKWebViewConfiguration()

配置偏好设置:

configuration.preferences.javaScriptEnabled = true // 启用 JavaScript
configuration.preferences.javaScriptCanOpenWindowsAutomatically = false // 禁止 JavaScript 自动打开窗口
configuration.preferences.minimumFontSize = 10 // 设置最小字体大小

配置用户交互控制:

configuration.userContentController.add(self, name: "myHandler") // 添加用户脚本消息处理程序
configuration.userContentController.addUserScript(myUserScript) // 添加用户脚本

配置 Web 视频播放行为:

configuration.allowsInlineMediaPlayback = true // 允许媒体以内联模式播放
configuration.mediaTypesRequiringUserActionForPlayback = .all // 设置媒体类型需要用户手动播放

配置网页内容预览行为:

configuration.dataDetectorTypes = [.phoneNumber, .link] // 启用电话号码和链接的数据检测

配置网页内容缩放行为:

configuration.userInterfaceStyle = .dark // 设置网页界面风格为暗黑模式
configuration.suppressesIncrementalRendering = false // 关闭增量渲染

配置其他属性:

configuration.websiteDataStore = WKWebsiteDataStore.default() // 使用默认的网站数据存储
configuration.applicationNameForUserAgent = "CustomApp/1.0" // 设置自定义的 User Agent 应用名称

实例


import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    @IBOutlet weak var progressView: UIProgressView!
    @IBOutlet weak var mainWebView: WKWebView!
    
    @IBOutlet weak var webBackBtn: UIButton!
    @IBOutlet weak var webForBtn: UIButton!
    
    private var observation: NSKeyValueObservation? = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()

        mainWebView.configuration.allowsInlineMediaPlayback = true
        mainWebView.configuration.mediaTypesRequiringUserActionForPlayback = .all
        
        mainWebView.backgroundColor = .clear
        mainWebView.isOpaque = false
        mainWebView.uiDelegate = self
        mainWebView.navigationDelegate = self
        observation = mainWebView.observe(\.estimatedProgress, options: [.new]) { [weak self] _, _ in
            guard let self = self else {return }
            self.progressView.progress = Float(self.mainWebView.estimatedProgress)
        }

        // 加载包含视频的网页
        if let url = URL(string: "https://www.example.com/video.html") {
            let request = URLRequest(url: url)
            mainWebView.load(request)
        }
    }
    
}


extension ViewController: WKNavigationDelegate, WKUIDelegate {
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        // 网页加载失败,隐藏进度条
        progressView.isHidden = true
        
        self.webForBtn.isEnabled = self.mainWebView.canGoForward
        self.webBackBtn.isEnabled = self.mainWebView.canGoBack
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        // 网页开始加载,显示进度条
        progressView.isHidden = false
        progressView.setProgress(0.08, animated: false)
    }
    
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        // 网页内容开始返回,更新进度条
        progressView.setProgress(0.12, animated: true)
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        // 网页加载失败,隐藏进度条
        progressView.isHidden = true
        
        self.webForBtn.isEnabled = self.mainWebView.canGoForward
        self.webBackBtn.isEnabled = self.mainWebView.canGoBack
    }
    
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        // 网页进程终止,隐藏进度条
        progressView.isHidden = true
        
        self.webForBtn.isEnabled = self.mainWebView.canGoForward
        self.webBackBtn.isEnabled = self.mainWebView.canGoBack
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 网页加载完毕,更新进度条
        progressView.setProgress(1.0, animated: true)
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.progressView.isHidden = true
        }
        self.webForBtn.isEnabled = self.mainWebView.canGoForward
        self.webBackBtn.isEnabled = self.mainWebView.canGoBack
    }

}

扩展

WKAudiovisualMediaTypes 枚举是用于配置在 WKWebView 中播放媒体时需要用户手动操作的类型。
以下是该枚举的成员以及对应的解释:

没有指定媒体类型,即不需要用户手动操作。
WKAudiovisualMediaTypeNone:

音频类型媒体,包括音乐、声音等,需要用户手动操作才能播放。
WKAudiovisualMediaTypeAudio:

视频类型媒体,包括视频文件、网络视频等,需要用户手动操作才能播放。
WKAudiovisualMediaTypeVideo:

所有类型的媒体都需要用户手动操作才能播放。
WKAudiovisualMediaTypeAll:

这些成员可以用于配置在 WKWebView 中触发媒体播放时用户的交互行为。
通过选择不同的成员,你可以控制在 WebView 中播放不同类型媒体时用户是否需要手动操作。

WKDataDetectorTypes 枚举是用于配置 WKWebView 中数据检测类型的枚举。
它定义了一些常见的数据类型,以便在 WebView 中对这些数据进行自动检测和处理。
以下是该枚举的成员以及对应的解释:

电话号码类型的数据,包括电话号码、拨号链接等。
WKDataDetectorTypePhoneNumber:

链接类型的数据,包括网页链接、URL 等。
WKDataDetectorTypeLink:

地址类型的数据,包括邮寄地址、地图位置等。
WKDataDetectorTypeAddress:

日历事件类型的数据,例如日期、时间等。
WKDataDetectorTypeCalendarEvent:

跟踪号类型的数据,例如快递单号。
WKDataDetectorTypeTrackingNumber:

航班号类型的数据,用于识别航班号码。
WKDataDetectorTypeFlightNumber:

查询建议类型的数据,用于识别查询建议。
WKDataDetectorTypeLookupSuggestion:

不检测任何数据类型。
WKDataDetectorTypeNone:

检测所有支持的数据类型。
WKDataDetectorTypeAll:


通过使用这些成员,你可以为 WKWebView 指定需要自动检测和处理的数据类型,以提供更好的用户体验。
例如,如果你启用了电话号码和链接的数据检测,在 WebView 中展示的电话号码和链接将会自动可点击并触发相应操作。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容