WKWebView Safari调试、JS互调、加载进度条、JS中alert、confirm、prompt
主要内容
- Safari调试
- swift/OC与JS互调
- 增加加载进度条
- 支持JS中alert、confirm、prompt
Safari调试
设置 —> safari --> 高级,开启JavaScript、网页检查器
打开Safari浏览器,选择调试的网页,同样在js里面可以断点调试:
swift/OC与JS互调
这里只介绍Swift,OC可以照着swift翻译即可
- swift调用JS,并传参数
先定义一个JS函数,如:
function add(params) {let msg = JSON.stringify(params);showMsg("调用了add函数")}
swift调用JS实际上就是调用WKWebView的evaluateJavaScript方法
/* @abstract Evaluates the given JavaScript string.@param javaScriptString The JavaScript string to evaluate.@param completionHandler A block to invoke when script evaluation completes or fails.@discussion The completionHandler is passed the result of the script evaluation or an error.Calling this method is equivalent to calling `evaluateJavaScript:inFrame:inContentWorld:completionHandler:` with:- A `frame` value of `nil` to represent the main frame- A `contentWorld` value of `WKContentWorld.pageWorld`*/open func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil)
参数javaScriptString就是JS的函数名+参数,如:
调用add的JS函数,javaScriptString为"add({\n “name” : “jack”\n})"
可以简单封装下调用方法:
/// 调用JS函数/// - Parameters:/// - jsFunName: JS函数名/// - params: 传给JS函数的参数/// - Returns:func callJSFunction(jsFunName: String, params: Any?) -> Void {var js = String(format: "%@()", jsFunName)if let valueStr = params as? String {js = String(format: "%@('%@')", jsFunName, valueStr)} else if let valueNum = params as? NSNumber {js = String(format: "%@(%@)", jsFunName, valueNum)} else if let valueBool = params as? Bool {if valueBool {js = jsFunName + "(true)"} else {js = jsFunName + "(false)"}} else if let valueDiction = params {if let temValue = converObjToJson(obj: valueDiction) {js = String(format: "%@(%@)", jsFunName, temValue)} else {js = String(format: "%@()", jsFunName)}} else {js = String(format: "%@()", jsFunName)}self.webView?.evaluateJavaScript(js) { (item, error) in}}
- JS调用swift,并传参数
在JS端调用window.webkit.messageHandlers.自定义一个名称.postMessage(params),如:
var params = {“name”: “JSName”};
window.webkit.messageHandlers.minus.postMessage(params);
这个自定义的名称需要提前设置到WKWebView上,设置方法:
/** @abstract Adds a script message handler to the main world used by page content itself.@param scriptMessageHandler The script message handler to add.@param name The name of the message handler.@discussion Calling this method is equivalent to calling addScriptMessageHandler:contentWorld:name:with [WKContentWorld pageWorld] as the contentWorld argument.*/open func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String)
如:
let userContent = WKUserContentController()// 配置JS可以调用的名称let jsCallFun: [String] = ["minus"]for value in jsCallFun {userContent.add(self, name: value)}let config = WKWebViewConfiguration()config.preferences = preferencesconfig.userContentController = userContentconfig.suppressesIncrementalRendering = true
配置完后,当JS调用window.webkit.messageHandlers.minus.postMessage(params);时会进入到WSWebView的WKScriptMessageHandler代理方法userContentController
如:
// MARK: - WKScriptMessageHandlerfunc userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {let name = message.name // 注册过的JS可调用的名称if name.elementsEqual("minus") {if let params = message.body as? NSDictionary { // JS传递的参数if let name = params.value(forKey: "name") as? String {minus(name: name)}}}}func minus(name: String) -> Void {showAlert(title: "Swift minus方法", message: "name:\(name)", modelArray: nil, cancelTitle: "确定", cancelHandle: {}, vc: self, sourceView: webView)}
总结:
我们常用的需求更多的场景应该是JS调用swift的某个方法后,再回调JS的某个方法,达到异步回调的效果,这时我们可以这样设计:
把JS的回调函数名当作参数传给swift的方法,swift处理完逻辑后直接调用这个参数:
var params = {"name": "JSName","callBackFun": "minusCallback"};
window.webkit.messageHandlers.minus.postMessage(params);
而swift端:
// MARK: - WKScriptMessageHandlerfunc userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {let name = message.name // 注册过的JS可调用的名称if name.elementsEqual("minus") {if let params = message.body as? NSDictionary { // JS传递的参数if let name = params.value(forKey: "name") as? String {let callback = params.value(forKey: "callBackFun") as? Stringminus(name: name, callBack: callback)}}}}func minus(name: String, callBack: String?) -> Void {showAlert(title: "Swift minus方法", message: "name:\(name)", modelArray: nil, cancelTitle: "确定", cancelHandle: { [weak self] inif let callBackFun = callBack {guard let self = self else { return }self.callJSFunction(jsFunName: callBackFun, params: nil)}}, vc: self, sourceView: webView)}
swift调用JS同理!
增加加载进度条
进度条使用第三方库NJKWebViewProgress
pod 'NJKWebViewProgress'
在WKWebView上面预留2个高度显示进度条,使用ReactiveCocoa监听WKWebView的进度:
self.webView?.reactive.signal(forKeyPath: "estimatedProgress").observeValues({ [weak self](result) inguard let self = self else {return}if let progress = result as? NSNumber {self.progressView?.setProgress(progress.floatValue, animated: true)if progress.floatValue >= 1.0 {self.progressWrapViewHeightConst.constant = 0}}})
其他地方涉及到进度的地方再优化下:
// MARK: - WKNavigationDelegate// MARK: 页面开始加载时调用func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {self.progressWrapViewHeightConst.constant = self.progressHeight}// MARK: 内容开始返回时调用func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {}func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {self.progressWrapViewHeightConst.constant = 0}func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {self.progressWrapViewHeightConst.constant = 0}func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {self.progressWrapViewHeightConst.constant = 0}
支持JS中alert、confirm、prompt
在JS端调用alert、confirm、prompt这几个方法,实际上会回调到WKWebView的WKUIDelegate代理中,对应的方法为:
@available(iOS 8.0, *)optional func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void)@available(iOS 8.0, *)optional func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void)@available(iOS 8.0, *)optional func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void)
需要实现具体方法才能有效果:
// MARK: - WKUIDelegatefunc webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {showAlert(title: "温馨提示", message: message, modelArray: nil, cancelTitle: "确定", cancelHandle: {completionHandler()}, vc: self, sourceView: webView)}func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {var modelArray: [AlertModel] = [AlertModel]()let model = AlertModel(title: "确定") {completionHandler(true)}modelArray.append(model)showAlert(title: "温馨提示", message: message, modelArray: modelArray, cancelTitle: "取消", cancelHandle: {completionHandler(false)}, vc: self, sourceView: webView)}func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {let alertController = UIAlertController(title: prompt, message: defaultText, preferredStyle: UIAlertController.Style.alert)alertController.addTextField { (txtField) intxtField.text = defaultText}alertController.addAction(UIAlertAction(title: "确定", style: UIAlertAction.Style.default, handler: { (alertAction) inlet txt = alertController.textFields?[0].textcompletionHandler(txt)}))self.present(alertController, animated: true) {}}
项目源码: https://codechina.csdn.net/ios1/projectcommon
如果觉得可以就点个
WKWebView Safari调试、JS互调、加载进度条、JS中alert、confirm、prompt相关推荐
- 原生JS实现加载进度条
分享一个原生JS实现的动态加载进度条特效,效果如下: 实现的代码如下: <!DOCTYPE html> <html><head><meta http-equi ...
- 一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)
// // OpenWebViewController.m // Treasure // // Created by 蓝蓝色信子 on 16/7/29. // Copyright © 2016年 GY ...
- 浅谈前端实现页面加载进度条以及 nprogress.js 的实现
以前在 Vue 的项目用了 nprogress 这个插件,一直对于其如何得知加载进度充满好奇,最近又看到了「前端如何实现页面加载进度条」这个问题,今天周六恰好一探究竟.以下仅为一家之言,如有异议,欢迎 ...
- 【原生JS插件】LoadingBar页面顶部加载进度条
先展示一下已经实现的效果: 预览地址:http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手机上的浏览器内置了页面的加载进度条,想用在pc上 ...
- js网页顶部线性页面加载进度条,jquery头部线性进度条总结
前言 网页顶部加载进度条,近年来很流行,很多网站都采用了这种加载方式.网上也有这样类似的插件,今天我们总结一下网页顶部线性页面加载进度条. 头部LoadingBar线性进度条总结 上面的代码只是静态效 ...
- pace.js – 加载进度条插件
这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...
- pace.js网页自动加载进度条插件-好东西
pace.js – 网页自动加载进度条插件 源码地址 https://github.com/HubSpot/pace 入Pace.js以及主题文件 Pace.js公开的API列表, Pace.star ...
- NProgress.js - 前端全站进度条插件 - 给你的网站添加一个加载进度条
0x00 前言 前几天给博客换了@Veen Zhao大佬的Cuteen主题,非常好看,但是因为不想让自己的博客和其他人的千篇一律,于是决定在Cuteen主题的前提下逐渐设计一些自己需要的东西.正巧前几 ...
- WKWebView加载进度条(仿微信)
WKWebView添加了estimatedProgress属性(double类型),我们可以利用该属性来设置UIProgressView github代码仓库上存放的Demo 为页面添加UIProgr ...
最新文章
- 你认识这些布道师吗?
- Activiti工作流内建数据库表分析
- 验算双中心重叠积分程序
- php 加密解密函数封装
- rf框架的缺点_2017热门开源自动化测试框架优缺点对比
- java解决XSS攻击常用方法总结
- PHP 处理TXT文件(打开/关闭/检查/读取)
- 基于TMS320VC5507的语音识别系统实现
- IntelliJ IDEA设置--类代码模板自定义(注释)
- CentOS7.0设置中文输入法
- 查看Casio PDA 的物理地址 MAC (DT-X7系列)
- content=IE=Edge是什么意思?
- c语言编写qq机器人软件,未编译的QQ机器人C语言版
- zabbix 参数 脚本_zabbix 自定义脚本短信报警
- 做APM领域德国队,笃信技术和极简体验的听云打造历程
- Java中Object类
- 洛朗级数与泰勒展开的区别
- 疫情查询 国内疫情显示“无网络”解决方法
- 考试系统mysql数据库设计_在线考试系统数据库设计(表)
- PNG透明背景显示之路
热门文章
分享一个原生JS实现的动态加载进度条特效,效果如下: 实现的代码如下: <!DOCTYPE html> <html><head><meta http-equi ...
// // OpenWebViewController.m // Treasure // // Created by 蓝蓝色信子 on 16/7/29. // Copyright © 2016年 GY ...
以前在 Vue 的项目用了 nprogress 这个插件,一直对于其如何得知加载进度充满好奇,最近又看到了「前端如何实现页面加载进度条」这个问题,今天周六恰好一探究竟.以下仅为一家之言,如有异议,欢迎 ...
先展示一下已经实现的效果: 预览地址:http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手机上的浏览器内置了页面的加载进度条,想用在pc上 ...
前言 网页顶部加载进度条,近年来很流行,很多网站都采用了这种加载方式.网上也有这样类似的插件,今天我们总结一下网页顶部线性页面加载进度条. 头部LoadingBar线性进度条总结 上面的代码只是静态效 ...
这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...
pace.js – 网页自动加载进度条插件 源码地址 https://github.com/HubSpot/pace 入Pace.js以及主题文件 Pace.js公开的API列表, Pace.star ...
0x00 前言 前几天给博客换了@Veen Zhao大佬的Cuteen主题,非常好看,但是因为不想让自己的博客和其他人的千篇一律,于是决定在Cuteen主题的前提下逐渐设计一些自己需要的东西.正巧前几 ...
WKWebView添加了estimatedProgress属性(double类型),我们可以利用该属性来设置UIProgressView github代码仓库上存放的Demo 为页面添加UIProgr ...