1.什么是 WKWebView?
WKWebView是UIKit框架中的一个视图组件,用于在iOS应用中显示Web内容。相比于旧版的UIWebView,WKWebView具有更好的性能、更低的内存占用以及更多的现代Web功能。它采用了WebKit引擎,能够渲染HTML、CSS和JavaScript,同时还支持与Web内容的交互。
2.使用 WKWebView
以下是使用WKWebView的基本步骤:
- 打开Xcode并创建一个新的Single View App项目。
- 打开Main.storyboard文件。
- 在显示
WKWebView的界面上,拖拽一个WKWebView组件用作容器。 - 在视图控制器的代码文件中,创建一个
IBOutlet来引用您在Storyboard中添加的WKWebView。 - 在视图控制器代码文件中,导入
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中常见方法的详细说明:
webView(_:decidePolicyFor:decisionHandler:): 这是WKNavigationDelegate的主要方法之一。当发起一个导航行为(如链接点击或页面跳转)时,此方法会被调用。可以在这里决定是否允许导航,以及如何处理导航行为。需要调用decisionHandler闭包,并传入.cancel或.allow来决定是否允许导航。webView(_:didStartProvisionalNavigation:): 在开始加载页面内容时调用。可以在这里执行一些UI操作,例如显示加载指示器。webView(_:didCommit:): 在开始接收网页数据并将其渲染时调用。在此阶段,页面的内容已经开始显示,可以继续进行一些UI更新。webView(_:didFinish:): 在页面加载完成后调用。可以在此方法中执行一些操作,例如隐藏加载指示器、更新界面元素等。webView(_:didFail:withError:): 如果页面加载失败,则会调用此方法。可以在这里处理加载错误,例如显示错误信息或执行其他操作。webView(_:didReceive:completionHandler:): 当接收到服务器的身份验证挑战时(例如需要登录时),此方法会被调用。可以在这里提供身份验证凭据。webView(_:didReceiveServerRedirectForProvisionalNavigation:): 当网页重定向时,此方法会被调用。可以在此方法中处理重定向的情况。webViewWebContentProcessDidTerminate(_:): 当WKWebView的Web内容进程终止时,此方法会被调用。可以在此重新加载页面或执行其他操作。
通过实现这些方法,可以全面控制WKWebView的导航行为和加载过程。例如,可以拦截导航行为以防止某些网页被加载,处理页面加载错误,实现自定义的身份验证等。在使用WKNavigationDelegate时,确保在适当的时机调用decisionHandler以控制导航的继续或取消。
5.通过 WKWebViewConfiguration 设置各种属性和选项
WKWebViewConfiguration是用于配置WKWebView的一个类,它允许您通过设置各种属性和选项,来定制和控制WKWebView的行为和外观。使用WKWebViewConfiguration,您可以在加载和显示Web内容时进行更细粒度的控制,以满足不同的应用需求。
以下是WKWebViewConfiguration中一些常见属性和配置选项的详细讲解:
processPool:WKProcessPool对象,用于共享Web内容处理的进程池。多个WKWebView可以共享同一个进程池,以便实现资源共享,如cookie、缓存等。preferences:WKPreferences对象,用于设置WKWebView的偏好选项,如是否启用JavaScript、是否允许图片加载等。userContentController:WKUserContentController对象,用于管理与JavaScript交互相关的内容,如添加自定义的JavaScript脚本、消息处理等。websiteDataStore:WKWebsiteDataStore对象,用于管理网站数据,如Cookies、缓存等。每个WKWebView可以有自己的数据存储,或者共享同一个数据存储。applicationNameForUserAgent: 设置应用程序的名称,将出现在User Agent中,用于标识应用程序。allowsInlineMediaPlayback: 一个布尔值,指定是否允许在WKWebView内直接播放音频或视频。mediaTypesRequiringUserActionForPlayback: 一个枚举值,用于设置媒体类型是否需要用户交互才能自动播放。selectionGranularity: 设置文本选取的粒度,可以是字符、词语、句子等。suppressesIncrementalRendering: 一个布尔值,用于控制是否抑制增量渲染,即在页面加载完成前禁止显示内容。ignoresViewportScaleLimits: 一个布尔值,指定是否忽略视口缩放限制。dataDetectorTypes: 设置要检测的数据类型,如电话号码、链接等。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中一些常见方法的详细说明:
webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:): 当Web页面调用alert函数时,该方法会被调用。您可以在这里显示一个警报框,并根据用户的操作调用completionHandler闭包。webView(_:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:): 当Web页面调用confirm函数时,该方法会被调用。您可以在这里显示一个确认框,并根据用户的选择调用completionHandler闭包。webView(_:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:): 当Web页面调用prompt函数时,该方法会被调用。您可以在这里显示一个输入框,并根据用户的输入调用completionHandler闭包。webView(_:createWebViewWith:for:windowFeatures:): 当Web页面请求创建新的WKWebView时,该方法会被调用。您可以在这里创建一个新的WKWebView实例,并返回它。webViewDidClose(_:): 当一个WKWebView被关闭时,该方法会被调用。您可以在这里执行一些清理操作。
当使用WKWebView加载包含JavaScript的alert、confirm和prompt函数的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 方法...
}
文章结束。