这里每天分享一个 iOS 的新知识,快来关注我吧
前言
在现在的开发中,要将 H5 页面展示在 App 中主要用到 WKWebView
。在 Web 网页中有一些经典的 Alert 弹窗,为了支持这种警报,需要实现一些 WKWebView.uiDelegate
回调。这篇文章主要来讲讲如何在 iOS WKWebView
上支持各种 Javascript
警报的代码示例:
UIDelegate
首先你的 webView
需要支持 WKWebView.uiDelegate
协议,它包含支持 Javascript
警报所需的方法。
ini
webKitView?.uiDelegate = self
WKWebView Javascript 警报消息
当 Web 上执行 window.alert
的时候,系统会调用 webView(_:, runJavaScriptAlertPanelWithMessage:, initiatedByFrame:, completionHandler:)
代理方法, 我们需要在这个方法中做出承接:
less
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let alert = UIAlertController(
title: "这是一个来自 JS 的 Alert",
message: "Alert 的内容为:\(message)",
preferredStyle: .alert
)
// 增加一个 完成 按钮
let okAction = UIAlertAction(
title: "完成",
style: .default,
handler: { _ in
completionHandler()
}
)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
}
当 Web 上执行 window.alert('测试 alert')
的时候,就会调用这个方法,并弹出我们的 UIAlertController
:
Javascript 确认操作
当在 js 中执行 window.confirm("message")
时就会调用 webView(_:, runJavaScriptConfirmPanelWithMessage:, initiatedByFrame:, completionHandler:)
方法,我们可以在此拦截,并自己弹出一个 UIAlertController
来让用户确认。
这个方法中的 completionHandler
来回调给 WebView
用户点了是或者否。
less
func webView(_ webView: WKWebView,
runJavaScriptConfirmPanelWithMessage message: String,
initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping (Bool) -> Void) {
// Set the message as the UIAlertController message
let alert = UIAlertController(
title: "这是一个来自 JS 的确认弹窗",
message: "需要确认的内容为:\(message)",
preferredStyle: .alert
)
// 添加一个确认按钮
let okAction = UIAlertAction(
title: "确认",
style: .default,
handler: { _ in
// 当用户点击确认,回调 true 给 webView
completionHandler(true)
}
)
alert.addAction(okAction)
// 添加一个取消按钮
let cancelAction = UIAlertAction(
title: "取消",
style: .cancel,
handler: { _ in
// 当用户点击取消,回调 false 给 webView
completionHandler(false)
}
)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
当 H5 上 js 调用 window.confirm("你确认吗?")
,就会在页面上看到:
Javascript 输入提示
当在 js 中执行 window.prompt()
时就会调用 webView(_:, runJavaScriptTextInputPanelWithPrompt prompt:, defaultText:, initiatedByFrame frame:, completionHandler:)
方法,我们可以在此拦截,并自己弹出一个 UIAlertController
来让用户输入内容。
less
func webView(_ webView: WKWebView,
runJavaScriptTextInputPanelWithPrompt prompt: String,
defaultText: String?,
initiatedByFrame frame: WKFrameInfo,
completionHandler: @escaping (String?) -> Void) {
let alert = UIAlertController(
title: "这是一个来自 JS 的输入框弹窗",
message: "提示词为:\(prompt)",
preferredStyle: .alert
)
// 添加一个输入框
alert.addTextField()
// 把默认值写进输入框
alert.textFields?.first?.text = defaultText
// 添加一个提交按钮
let submitAction = UIAlertAction(
title: "提交",
style: .default,
handler: { [unowned alert] _ in
// 把用户输入的内容回调给 js
let input = alert.textFields?.first
completionHandler(input?.text)
}
)
alert.addAction(submitAction)
present(alert, animated: true, completion: nil)
}
当 js 执行 window.prompt('请输入内容', '这是输入框的默认值')
,就会在页面上看到我们自定义的带输入框的 Alert:
重要的一点
如果你决定使用这种方式承接 js 的警报弹窗,那么这三个方法的 completionHandler
回调一定要执行,否则当 js 调用到对应的方法时 App 会发生崩溃,崩溃日志为:
vbnet
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason:
'Completion handler passed to
-[TestProject.ViewController webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]
was not called'
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!