WKWebview
监听 WKWebview 属性
可监听
title
,loading
,estimatedProgress
,URL
,canGoBack
,canGoForward
1import RxSwift
2import RxCocoa
3import WebKit
4extension Reactive where Base: WKWebView {
5 // 标题
6 public var title: Observable<String> {
7 return self.observeWeakly(String.self, "title").map{$0 ?? ""}
8 }
9 // url
10 public var url: Observable<URL?> {
11 return self.observeWeakly(URL.self, "URL")
12 }
13 // 加载中
14 public var loading: Observable<Bool> {
15 return self.observeWeakly(Bool.self, "loading").map{$0 ?? false}
16 }
17 // 加载进度
18 public var progress: Observable<Float> {
19 return self.observeWeakly(Double.self, "estimatedProgress").map { Float($0 ?? 0.0) }
20 }
21 // 可以后退
22 public var canGoBack: Observable<Bool> {
23 return self.observeWeakly(Bool.self, "canGoBack").map{ $0 ?? false}
24 }
25 // 可以前进
26 public var canGoForward: Observable<Bool> {
27 return self.observeWeakly(Bool.self, "canGoForward").map { $0 ?? false }
28 }
29}
那些被 WKWebview 抛弃的属性
在 UIWebview 中有这么一个属性 paginationMode 翻页模式,做一些阅读器的功能会使用到,它有五个枚举值:
- unpaginated 无分页模式
- leftToRight 从左到右
- rightToLeft 从右到左
- topToBottom 从上到下
- bottomToTop 从下到上
paginationMode 属性虽然被 WKWebView 抛弃了,单还是可以通过 CSS 实现
1body {
2 /* 翻页模式 x:水平,y:垂直 */
3 overflow: -webkit-paged-y !important;
4 /* 翻页方向 t:上,l:左,b:下,r:右, ttb:从上到下 */
5 direction: ttb !important;
6}
注入 JS 脚本
WKWebView 的 configuration 属性下 userContentController 管理用户脚本
1extension WKWebViewConfiguration {
2 /// 添加用户脚本
3 /// - Parameters:
4 /// - script: js脚本代码
5 /// - injectionTime: 注入时间
6 /// - forMainFrameOnly: 是否仅在主Frame注入
7 /// - world: 关键词
8 public func addUserScript(script: String, injectionTime: WKUserScriptInjectionTime, forMainFrameOnly: Bool, world: String? = nil) {
9 let userScript = WKUserScript(source: script, injectionTime: injectionTime, forMainFrameOnly: forMainFrameOnly)
10 addUserScript(script: userScript)
11 }
12
13 /// 添加用户脚本
14 /// - Parameters:
15 /// - fileName: js脚本文件名
16 /// - injectionTime: 注入时间
17 /// - forMainFrameOnly: 是否仅在主Document注入
18 /// - world: 关键词
19 public func addUserScript(fileName: String, injectionTime: WKUserScriptInjectionTime, forMainFrameOnly: Bool, world: String? = nil) throws {
20 do {
21 let source = try String(contentsOfFile: Bundle.main.path(forResource: fileName, ofType: "js") ?? "", encoding: .utf8)
22 let userScript = WKUserScript(source: source, injectionTime: injectionTime, forMainFrameOnly: forMainFrameOnly)
23 addUserScript(script: userScript)
24 } catch {
25 throw error
26 }
27 }
28
29 /// 添加用户脚本
30 /// - Parameter script: 用户脚本
31 func addUserScript(script: WKUserScript) {
32 userContentController.addUserScript(script)
33 }
34
35 /// 移除所有的用户脚本
36 public func removeAllUserScript() {
37 if userContentController.userScripts.count > 0 {
38 userContentController.removeAllUserScripts()
39 }
40 }
41}
禁用 JavaScript
禁用 JavaScript 后,Web视图不会执行Web内容引用的JavaScript代码。这包括在内联<script>
元素、javascript:URL和所有其他引用的JavaScript内容中找到的JavaScript代码。但不会影响 WKUserScripts、evaluteJavaScript、callAsyncJavaScript,它们任可以执行。
1extension WKWebViewConfiguration {
2 /// 设置是否启用 JavaScript
3 /// - Parameter enabled: 是否启用
4 public func setupJavaScriptEnabled(_ enabled: Bool) {
5 if #available(iOS 14.0, *) {
6 defaultWebpagePreferences.allowsContentJavaScript = enabled
7 } else {
8 preferences.javaScriptEnabled = enabled
9 }
10 }
11}
执行 JS 脚本
WKWebView 提供了直接执行 JS 脚本的方法 evaluateJavaScript(_:completionHandler:)
1webView.evaluateJavaScript("java script") { result, error in
2 // result 执行脚本的结果
3 // error 执行脚本的错误
4}
接收网页发送的消息
1class ClassName {
2 /// 添加脚本消息处理
3 /// - Parameters:
4 /// - handler: 消息处理
5 /// - name: 脚本消息名称
6 public func addScriptMessageHandler(_ handler: WKScriptMessageHandler, name: String) {
7 webview.configuration.userContentController.add(handler, name: name)
8 }
9}
10
11//在网页中发送消息
12//function postMessage(message){
13// window.webkit.messageHandlers.messageName.postMessage(message);
14//}
15
16//消息处理者需要遵守 WKScriptMessageHandler 协议并实现方法
17extension ClassName: WKScriptMessageHandler{
18 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
19 //接收到消息的名称
20 message.name
21 //接收到消息的内容
22 message.body
23 }
24}
滑动之后白屏问题
子类继承 WKWebView 后,对子类进行扩展并遵守 UIScrollViewDelegate 协议,实现了 UIScrollViewDelegate 中的方法
1//BaseWebView.swift
2BaseWebView: WKWebView {
3 ...
4}
5extension BaseWebView: UIScrollViewDelegate {
6 public func scrollViewDidScroll(_ scrollView: UIScrollView) {
7 ...
8 }
9
10 public func scrollView ...
11}
用 BaseWebView 或者其子类加载网页后,滑动的时候就会出现网页有部分内容没有进行渲染