主要内容

  • 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相关推荐

  1. 原生JS实现加载进度条

    分享一个原生JS实现的动态加载进度条特效,效果如下: 实现的代码如下: <!DOCTYPE html> <html><head><meta http-equi ...

  2. 一个KVO 实现WKWebView加载进度条的例子 (注意最后移除观察者)

    // // OpenWebViewController.m // Treasure // // Created by 蓝蓝色信子 on 16/7/29. // Copyright © 2016年 GY ...

  3. 浅谈前端实现页面加载进度条以及 nprogress.js 的实现

    以前在 Vue 的项目用了 nprogress 这个插件,一直对于其如何得知加载进度充满好奇,最近又看到了「前端如何实现页面加载进度条」这个问题,今天周六恰好一探究竟.以下仅为一家之言,如有异议,欢迎 ...

  4. 【原生JS插件】LoadingBar页面顶部加载进度条

    先展示一下已经实现的效果: 预览地址:http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手机上的浏览器内置了页面的加载进度条,想用在pc上 ...

  5. js网页顶部线性页面加载进度条,jquery头部线性进度条总结

    前言 网页顶部加载进度条,近年来很流行,很多网站都采用了这种加载方式.网上也有这样类似的插件,今天我们总结一下网页顶部线性页面加载进度条. 头部LoadingBar线性进度条总结 上面的代码只是静态效 ...

  6. pace.js – 加载进度条插件

    这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...

  7. pace.js网页自动加载进度条插件-好东西

    pace.js – 网页自动加载进度条插件 源码地址 https://github.com/HubSpot/pace 入Pace.js以及主题文件 Pace.js公开的API列表, Pace.star ...

  8. NProgress.js - 前端全站进度条插件 - 给你的网站添加一个加载进度条

    0x00 前言 前几天给博客换了@Veen Zhao大佬的Cuteen主题,非常好看,但是因为不想让自己的博客和其他人的千篇一律,于是决定在Cuteen主题的前提下逐渐设计一些自己需要的东西.正巧前几 ...

  9. WKWebView加载进度条(仿微信)

    WKWebView添加了estimatedProgress属性(double类型),我们可以利用该属性来设置UIProgressView github代码仓库上存放的Demo 为页面添加UIProgr ...

最新文章

  1. 你认识这些布道师吗?
  2. Activiti工作流内建数据库表分析
  3. 验算双中心重叠积分程序
  4. php 加密解密函数封装
  5. rf框架的缺点_2017热门开源自动化测试框架优缺点对比
  6. java解决XSS攻击常用方法总结
  7. PHP 处理TXT文件(打开/关闭/检查/读取)
  8. 基于TMS320VC5507的语音识别系统实现
  9. IntelliJ IDEA设置--类代码模板自定义(注释)
  10. CentOS7.0设置中文输入法
  11. 查看Casio PDA 的物理地址 MAC (DT-X7系列)
  12. content=IE=Edge是什么意思?
  13. c语言编写qq机器人软件,未编译的QQ机器人C语言版
  14. zabbix 参数 脚本_zabbix 自定义脚本短信报警
  15. 做APM领域德国队,笃信技术和极简体验的听云打造历程
  16. Java中Object类
  17. 洛朗级数与泰勒展开的区别
  18. 疫情查询 国内疫情显示“无网络”解决方法
  19. 考试系统mysql数据库设计_在线考试系统数据库设计(表)
  20. PNG透明背景显示之路

热门文章

  1. CMake 打包已经存在的动态库生成 target
  2. Flume-0.9.4数据插入HBase-0.96
  3. Adding a QR Code Reader in Flex on Android
  4. 二进制,十进制,十六进制
  5. ASPJPEG缩略图生成函数
  6. 三维重建【一】——————(深度学习方式)
  7. 更好的Java虚拟机Zing: 更好的性能,无停顿,更快的启动
  8. 鸡肋的PHP单例模式
  9. 用ASP.NET上传大文件
  10. MFC静态文本控件设置超链接