1.什么是 WKWebView

WKWebViewUIKit结构中的一个视图组件,用于在iOS运用中显现Web内容。比较于旧版的UIWebViewWKWebView具有更好的性能、更低的内存占用以及更多的现代Web功能。它采用了WebKit引擎,能够烘托HTML、CSS和JavaScript,同时还支持与Web内容的交互。

2.运用 WKWebView

以下是运用WKWebView的基本过程:

  1. 打开Xcode并创立一个新的Single View App项目。
  2. 打开Main.storyboard文件。
  3. 在显现WKWebView的界面上,拖拽一个WKWebView组件用作容器。
  4. 在视图操控器的代码文件中,创立一个IBOutlet来引证您在Storyboard中添加的WKWebView
  5. 在视图操控器代码文件中,导入WebKit结构:
import WebKit

创立一个WKWebView实例,并将其添加到容器视图中:

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    @IBOutlet weak var webViewContainer: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置 WKNavigationDelegate
        webViewContainer.navigationDelegate = self
        // 加载网页
        if let url = URL(string: "https://www.example.com") {
            let request = URLRequest(url: url)
            webViewContainer.load(request)
        }
    }
    // ...
}
}

用代码创立WKWebView

创立一个WKWebView实例,并将其添加到容器视图中:

import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // 创立 WKWebView 实例
        webView = WKWebView(frame: view.bounds)
        webView.navigationDelegate = self
        // 将 WKWebView 添加到容器视图中
        view.addSubview(webView)
    }
    // ...
}

运用load()办法加载网页内容:

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

假如当前页面就只有一个WKWebView,还能够在Main.storyboard去掉WKWebView然后直接重写视图操控器生命周期loadView函数。

    var webView: WKWebView!
  //自定义根视图--当整个页面是WebView时推荐这么做
  override func loadView() {
    let config = WKWebViewConfiguration()
    config.allowsInlineMediaPlayback = true
    webView = WKWebView(frame: .zero, configuration: config)
   
    //用于操控是否答应运用手势进行前进和撤退的导航
    webView.allowsBackForwardNavigationGestures = true
    webView.uiDelegate = self
    webView.navigationDelegate = self
    view = webView
  }

直接替换页面根视图,相对比较节省资源。

3.与 Web 内容交互

WKWebView不仅能够加载网页内容,还能够与Web内容进行交互。您能够经过JavaScript与Web页面通讯,然后完成从运用中向Web内容发送数据,或许从Web内容接纳数据。以下是一些常见的交互办法:

  • 经过JavaScript注入,向Web页面传递数据:
let script = "myFunction('Hello from iOS!');"
webView.evaluateJavaScript(script, completionHandler: nil)
  • 经过WKScriptMessageHandler协议,从Web页面接纳数据:
class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
        let userContentController = webView.configuration.userContentController
        userContentController.add(self, name: "messageHandlerName")
    }
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "messageHandlerName", let messageBody = message.body as? String {
            print("Received message from web: \(messageBody)")
        }
    }
    // ...
}

4.完成 WKNavigationDelegate

假如期望在WKWebView的加载过程中监控和处理一些事情,能够完成WKNavigationDelegate协议。例如,能够在页面加载完成后履行某些操作,或许处理加载错误等状况。

class ViewController: UIViewController, WKNavigationDelegate {
    // ...
    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
        // 设置 WKNavigationDelegate
        webView.navigationDelegate = self
    }
    // 完成 WKNavigationDelegate 办法
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("Web page loaded successfully.")
    }
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("Web page loading failed with error: \(error.localizedDescription)")
    }
    // ...
}

WKNavigationDelegate是一个用于WKWebView的协议,它答应监控和操控WKWebView的导航行为,包括网页加载、跳转、错误处理等。经过完成WKNavigationDelegate的办法,能够在不同的导航事情产生时履行特定的操作。

以下是WKNavigationDelegate中常见办法的详细阐明:

  1. webView(_:decidePolicyFor:decisionHandler:) : 这是WKNavigationDelegate的主要办法之一。当建议一个导航行为(如链接点击或页面跳转)时,此办法会被调用。能够在这里决议是否答应导航,以及如何处理导航行为。需求调用decisionHandler闭包,并传入.cancel.allow来决议是否答应导航。
  2. webView(_:didStartProvisionalNavigation:) : 在开端加载页面内容时调用。能够在这里履行一些UI操作,例如显现加载指示器。
  3. webView(_:didCommit:) : 在开端接纳网页数据并将其烘托时调用。在此阶段,页面的内容已经开端显现,能够继续进行一些UI更新。
  4. webView(_:didFinish:) : 在页面加载完成后调用。能够在此办法中履行一些操作,例如隐藏加载指示器、更新界面元素等。
  5. webView(_:didFail:withError:) : 假如页面加载失败,则会调用此办法。能够在这里处理加载错误,例如显现错误信息或履行其他操作。
  6. webView(_:didReceive:completionHandler:) : 当接纳到服务器的身份验证挑战时(例如需求登录时),此办法会被调用。能够在这里提供身份验证凭证。
  7. webView(_:didReceiveServerRedirectForProvisionalNavigation:) : 当网页重定向时,此办法会被调用。能够在此办法中处理重定向的状况。
  8. webViewWebContentProcessDidTerminate(_:) : 当WKWebView的Web内容进程终止时,此办法会被调用。能够在此重新加载页面或履行其他操作。

经过完成这些办法,能够全面操控WKWebView的导航行为和加载过程。例如,能够拦截导航行为以避免某些网页被加载,处理页面加载错误,完成自定义的身份验证等。在运用WKNavigationDelegate时,保证在适当的时机调用decisionHandler以操控导航的继续或取消。

5.经过 WKWebViewConfiguration 设置各种特点和选项

WKWebViewConfiguration是用于装备WKWebView的一个类,它答应您经过设置各种特点和选项,来定制和操控WKWebView的行为和外观。运用WKWebViewConfiguration,您能够在加载和显现Web内容时进行更细粒度的操控,以满足不同的运用需求。

以下是WKWebViewConfiguration中一些常见特点和装备选项的详细解说:

  1. processPool: WKProcessPool目标,用于同享Web内容处理的进程池。多个WKWebView能够同享同一个进程池,以便完成资源同享,如cookie、缓存等。
  2. preferences: WKPreferences目标,用于设置WKWebView的偏好选项,如是否启用JavaScript、是否答应图片加载等。
  3. userContentController: WKUserContentController目标,用于办理与JavaScript交互相关的内容,如添加自定义的JavaScript脚本、消息处理等。
  4. websiteDataStore: WKWebsiteDataStore目标,用于办理网站数据,如Cookies、缓存等。每个WKWebView能够有自己的数据存储,或许同享同一个数据存储。
  5. applicationNameForUserAgent: 设置运用程序的称号,将出现在User Agent中,用于标识运用程序。
  6. allowsInlineMediaPlayback: 一个布尔值,指定是否答应在WKWebView内直接播映音频或视频。
  7. mediaTypesRequiringUserActionForPlayback: 一个枚举值,用于设置媒体类型是否需求用户交互才干自动播映。
  8. selectionGranularity: 设置文本选取的粒度,能够是字符、词语、句子等。
  9. suppressesIncrementalRendering: 一个布尔值,用于操控是否按捺增量烘托,即在页面加载完成前禁止显现内容。
  10. ignoresViewportScaleLimits: 一个布尔值,指定是否疏忽视口缩放限制。
  11. dataDetectorTypes: 设置要检测的数据类型,如电话号码、链接等。
  12. defaultWebpagePreferences: WKWebpagePreferences目标,用于设置默认的网页首选项,如预览类型、格式等。

经过装备WKWebViewConfiguration,能够调整WKWebView的行为和外观。在创立WKWebView实例时,将这些装备运用于装备目标,然后将装备目标传递给WKWebView的初始化办法,然后完成对WKWebView的定制。

let configuration = WKWebViewConfiguration()
configuration.preferences.javaScriptEnabled = true
configuration.userContentController = WKUserContentController()
let webView = WKWebView(frame: CGRect.zero, configuration: configuration)

5.经过 WKUIDelegate 处理与用户界面相关的事情

WKUIDelegate是一个用于WKWebView的协议,用于处理与用户界面相关的事情,如弹出警报框、承认框、输入框等。经过完成WKUIDelegate中的办法,您能够在WKWebView中的Web内容需求显现与用户界面交互的元素时,履行相应的操作。

以下是WKUIDelegate中一些常见办法的详细阐明:

  1. webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:) : 当Web页面调用alert函数时,该办法会被调用。您能够在这里显现一个警报框,并根据用户的操作调用completionHandler闭包。
  2. webView(_:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:) : 当Web页面调用confirm函数时,该办法会被调用。您能够在这里显现一个承认框,并根据用户的选择调用completionHandler闭包。
  3. webView(_:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:) : 当Web页面调用prompt函数时,该办法会被调用。您能够在这里显现一个输入框,并根据用户的输入调用completionHandler闭包。
  4. webView(_:createWebViewWith:for:windowFeatures:) : 当Web页面恳求创立新的WKWebView时,该办法会被调用。您能够在这里创立一个新的WKWebView实例,并回来它。
  5. webViewDidClose(_:) : 当一个WKWebView被封闭时,该办法会被调用。您能够在这里履行一些整理操作。

当运用WKWebView加载包括JavaScript的alertconfirmprompt函数的Web页面时,能够经过完成WKUIDelegate的相应办法来定制这些弹窗的外观和行为。以下是如安在WKUIDelegate中定制这三种弹窗的示例:

import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
    var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let configuration = WKWebViewConfiguration()
        configuration.preferences.javaScriptEnabled = true
        // 创立 WKWebView 实例并设置 WKUIDelegate
        webView = WKWebView(frame: view.bounds, configuration: configuration)
        webView.uiDelegate = self
        view.addSubview(webView)
        // 加载包括弹窗调用的 Web 页面
        if let url = URL(string: "https://www.example.com") {
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }
    // 完成 WKUIDelegate 办法来定制弹窗
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        // 创立自定义的警报框
        let alertController = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
            // 用户点击了OK按钮后调用completionHandler
            completionHandler()
        }))
        // 显现警报框
        self.present(alertController, animated: true, completion: nil)
    }
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        // 创立自定义的承认框
        let alertController = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { _ in
            // 用户点击了Cancel按钮后调用completionHandler
            completionHandler(false)
        }))
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
            // 用户点击了OK按钮后调用completionHandler
            completionHandler(true)
        }))
        // 显现承认框
        self.present(alertController, animated: true, completion: nil)
    }
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        // 创立自定义的输入框
        let alertController = UIAlertController(title: "Input", message: prompt, preferredStyle: .alert)
        alertController.addTextField(configurationHandler: { textField in
            textField.text = defaultText
        })
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { _ in
            // 用户点击了Cancel按钮后调用completionHandler
            completionHandler(nil)
        }))
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
            // 用户点击了OK按钮后调用completionHandler
            completionHandler(alertController.textFields?.first?.text)
        }))
        // 显现输入框
        self.present(alertController, animated: true, completion: nil)
    }
    // 完成其他 WKUIDelegate 办法...
}

文章结束。