web页面和app直接的交互是很常见的东西,之前尝试过flex和js的相互调用以及android和js的相互调用,却只有ios没试过,据说比较复杂。周末花了点时间研究了一下,确实和其他的不太一样,但是 也不见复杂。

要知道的事情

ios的webview有2个类,一个叫UIWebView,另一个是WKWebView。两者的基础方法都差不多,本文重点是后者,他是取代UIWebView出现的,在app开发者若不需要兼容ios8之前版本,都应该使用WKWebVIew。

WKWebView 是苹果在 iOS 8 中引入的新组件,目的是给出一个新的高性能的 Web View 解决方案,摆脱过去 UIWebView 的老旧笨重特别是内存占用量巨大的问题,它使用Nitro JavaScript引擎,这意味着所有第三方浏览器运行JavaScript将会跟safari一样快.

ios9默认是不允许加载http请求的,对于webview,加载http网页也是不允许的。可以通过修改info.plist取消http限制

在项目中找到info.plist,源文件形式打开,添加下面内容

<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

dome截图

大纲

  • UIWebView使用

    • 加载网页或本地页面
    • app调js方法
    • js调app方法
  • WKWebView的使用

    • 加载页面,前进,后退,刷新,进度条
    • 前进,后退,刷新,进度条
    • js中alert的拦截
    • app调js方法
    • js调app方法
    • webView生命周期和跳转代理
  • web页面

  • 文章demo

  • 参考文章

UIWebView使用


UIVebView现在已经弃用,ios8以上都应该用新的WKWebview,所以UIWebView我就随意说说,大家随意看看。

加载网页或本地页面

//从本地加载html let path:String! = NSBundle.mainBundle().pathForResource("index", ofType: "html") webView.loadRequest(NSURLRequest(URL: NSURL.fileURLWithPath(path))) //从网络加载 webView.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.bing.com")!))

注意点: 1. ios9默认不能加载http请求,需要声明 2. uiwebView网络请求会进入ternal func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool 委托,委托中若return false,也不会继续加载

app调js方法

app调用js方法使用的是 webView.stringByEvaluatingJavaScriptFromString() 这个方法。它可以直接执行一段js代码

//调用js无参数的方法 webView.stringByEvaluatingJavaScriptFromString("hi()") //调用js有参数的方法hello(msg) let js = String(format: "hello('%@')", "liuyanwei") webView.stringByEvaluatingJavaScriptFromString(js) //调用js的参数为json对象 let js = String(format: "hello(%@)", "{'obj':'liuyanwei'}") webView.stringByEvaluatingJavaScriptFromString(js) //从文件中加载一段js代码然后执行 do{ let jsString = try String(contentsOfFile: NSBundle.mainBundle().pathForResource("test", ofType: "js")!,encoding: NSUTF8StringEncoding) self.webView.stringByEvaluatingJavaScriptFromString(jsString) } catch{} //直接执行alert webView.stringByEvaluatingJavaScriptFromString("alert('hi')") //执行有返回值的js函数 NSLog("%@", webView.stringByEvaluatingJavaScriptFromString("getName()")!)

相关的js代码

var hi = function(){ alert("hello") $(".info").html("hi"); } var hello = function(msg){ alert("hello " + msg) if(msg.obj != undefined) alert(msg.obj) } var getName = function(){ return "liuyanwei" }

js调app方法

很多人觉得,为什么UIWebView中,js调用app的方式怎么那么奇怪,其实应该这样说,UIWebView没有办法直接使用js调用app,但是可以通过拦截request的方式间接实现js调用app方法。

既然是拦截url,那你就可以任意方式去规定想要调用的url的路径和app中方法转换的方式。我这里使用协议和路径的方式,例如我拦截到的url是 "hello://hello_liuyanwei" ,我就把hello当做想调用的方法,路径当做参数。这种方式不一定好,但是使用起来还是挺方便的。

js中调用app的方法如下:

//这段代码是原生js代码,在js中的作用是做页面跳转 //webView通过拦截url请求方式拦截到request,通过解析从而调用 ios hello方法,参数是hello_liuyanwei document.location = "hello://hello_liuyanwei";
//webView 需要实现UIWebViewDelegate委托方法 // class ViewController: UIViewController,UIWebViewDelegate .... // webView.delegate = self func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool{ //如果请求协议是hello 这里的hello来自js的调用,在js中设为 document.location = "hello://liuyanwei 你好"; //scheme:hello ,msg:liuyanwei 你好 //通过url拦截的方式,作为对ios原生方法的呼叫 if request.URL?.scheme == "hello"{ let method:String = request.URL?.scheme as String! let sel = Selector(method+":") self.performSelector(sel, withObject:request.URL?.host) request.URL?.path //如果return true ,页面加载request,我们只是当做协议使用所以不能页面跳转 return false } return true }

最后说一下关于js调用app的返回值。app调js可以有返回值,但是js调app是通过间接的拦截request方式实现,它根本就不算方法调用,所以应该是不存在可以直接产生返回值的(如果不对欢迎指正)。当然如果需要app对js的调用有所响应,可以通过回叫函数的方式回应js。可以在调用app的时候增加一个js回叫函数名 app在处理完之后可以呼叫回叫函数并把需要的参数通过回叫函数的方式进行传递。

WKWebView的使用


WKWebVIew是UIWebView的代替品,新的WebKit框架把原来的功能拆分成许多小类。本例中主要用到了WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler三个委托和配置类WKWebViewConfiguration去实现webView的request控制,界面控制,js交互,alert重写等功能。 使用WKWebView需要引入#import <WebKit/WebKit.h>

加载页面,配置委托和手势等

//加载页面 config = WKWebViewConfiguration() //设置位置和委托 webView =WKWebView(frame: self.webWrap.frame, configuration: config) webView.navigationDelegate = self webView.UIDelegate = self self.webWrap.addSubview(webView) //加载网页 //webView.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.bing.com")!)) //加载本地页面 webView.loadRequest(NSURLRequest(URL: NSURL.fileURLWithPath(NSBundle.mainBundle().pathForResource("index", ofType: "html")!))) //允许手势,后退前进等操作 webView.allowsBackForwardNavigationGestures = true

前进,后退,刷新,进度条

//前进 webView.goBack() //后退 webView.goForward() //刷新 let request= NSURLRequest(URL:webView.URL!) webView.loadRequest(request) //监听是否可以前进后退,修改btn.enable属性 webView.addObserver(self, forKeyPath: "loading", options: .New, context: nil) //监听加载进度 webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil) //重写self的kvo方法 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if (keyPath == "loading") { gobackBtn.enabled = webView.canGoBack forwardBtn.enabled = webView.canGoForward } if (keyPath == "estimatedProgress") { //progress是UIProgressView progress.hidden = webView.estimatedProgress==1 progress.setProgress(Float(webView.estimatedProgress), animated: true) }}

js中alert的拦截

在WKWebview中,js的alert是不会出现任何内容的,你必须重写WKUIDelegate委托的runJavaScriptAlertPanelWithMessage message方法,自己处理alert。类似的还有Confirm和prompt也和alert类似,这里我只以alert为例。

//alert捕获 func webView(webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: () -> Void) { // completionHandler() let alert = UIAlertController(title: "ios-alert", message: "\(message)", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "ok", style: .Default, handler:nil)) alert.addAction(UIAlertAction(title: "cancel", style: .Cancel, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) }

app调js方法

WKWebView调用js方法和UIWebView类似,一个是evaluateJavaScript,一个是stringByEvaluatingJavaScriptFromString。获取返回值的方式不同,WKWebView用的是回叫函数获取返回值

//直接调用js webView.evaluateJavaScript("hi()", completionHandler: nil) //调用js带参数 webView.evaluateJavaScript("hello('liuyanwei')", completionHandler: nil) //调用js获取返回值 webView.evaluateJavaScript("getName()") { (any,error) -> Void in NSLog("%@", any as! String) }

js调app方法

UIwebView没有js调app的方法,而在WKWebView中有了改进。具体步骤分为app注册handler,app处理handler委托,js调用三个步骤

1:注册handler需要在webView初始化之前,如示例,注册了一个webViewApp的handler

config = WKWebViewConfiguration() //注册js方法 config.userContentController.addScriptMessageHandler(self, name: "webViewApp") webView = WKWebView(frame: self.webWrap.frame, configuration: config)

2:处理handler委托。ViewController实现WKScriptMessageHandler委托的func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)方法

//实现WKScriptMessageHandler委托 class ViewController:WKScriptMessageHandler //实现js调用ios的handle委托 func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) { //接受传过来的消息从而决定app调用的方法 let dict= message.body as! Dictionary<String,String> let method:String = dict["method"]! let param1:String = dict["param1"]! if method=="hello"{ hello(param1) } }

3:js调用

通过 window.webkit.messageHandlers.webViewApp找到之前注册的handler对象,然后调用postMessage方法把数据传到app,app通过上一步的方法解析方法名和参数

var message = { 'method' : 'hello', 'param1' : 'liuyanwei', }; window.webkit.messageHandlers.webViewApp.postMessage(message);

如果需要app对js的调用有所响应,可以通过回叫函数的方式回应js。可以在调用app的时候增加一个js回叫函数名 app在处理完之后可以呼叫回叫函数并把需要的参数通过回叫函数的方式进行传递

webView生命周期和跳转代理

该代理提供的方法,可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转

// 页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; // 当内容开始返回时调用 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation*)navigation; // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; // 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation; // 接收到服务器跳转请求之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到响应后,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 在发送请求之前,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

web页面


随便说两句web页面,demo中的web前段用了jquery去操作dom,btn是在js中添加的,btn的点击事件也在js中。另外随便写了几个css让页面稍微美观一些。web页面都在项目文件夹下的web文件夹中。大家其实也不必看,因为调用的app的js代码在文中都有单独贴出。

参考文章


本文也只是用了一些基本的用法,大家想了解更多,可以看看下面的三篇文章做补充阅读。但是现在也没发现有把webView这块写的很全很详细的文章,今后要是看见我会继续补充在这里。

  • WKWeb?View
  • iOS 8 WebKit框架概览(上)译文
  • iOS 8 WebKit框架概览(下)译文

demo


我博客中大部分示例代码都上传到了github,地址是:https://github.com/coolnameismy/demo,点击跳转代码下载地址

本文代码存放目录是ios-WebView,本demo没做界面自适应,为了保证效果请用iPhone6及以上模拟器打开

如果大家支持,请github上follow和star

dome截图

UIWebView和WKWebView的使用及js交互相关推荐

  1. WKWebView的使用与JS交互详细解读

    前言: WKWebView 这是在iOS8.0之后增加的一个比UIWebView更加完善和强大的控件!看网上关于它的博客也是有许多的了,从各个方面总结一下这个WKWebView看网上说它主要是为了和J ...

  2. ios传值给js_深入剖析 iOS 与 JS 交互

    前言 Web 页面中的 JS 与 iOS Native 如何交互是每个 iOS 猿必须掌握的技能.而说到 Native 与 JS 交互,就不得不提一嘴 Hybrid. Hybrid 的翻译结果并不是很 ...

  3. swift中WKWebView和JS交互实现

    在Swift中加载HTML网页有两个view,分别是WKWebView和UIWebView,这里我使用的是WKWebView 这里分享一下我的写法: 1.定义变量WKWebView: lazy var ...

  4. iOS WKWebView和JS交互的两种方式

    2019独角兽企业重金招聘Python工程师标准>>> 本文介绍两种方式实现iOS WKWebView和JS交互 WKWebViewConfiguration注入WKScriptMe ...

  5. 对 WKWebView js交互的简单封装

    文章目录 1.WKWebView使用流程 2.核心方法 3.封装流程 3.1.初始化 3.2.加载URL 3.3.OC与js交互 3.3.1.监听js消息 3.3.2.注入js消息 3.3.3.移除j ...

  6. IOS开发 - UIWebView(用法全面介绍,含最全的JS交互)

    前两天我写了一套关于JS与OC交互的三种方法的文章,但是发现自己对UIWebView理解的还是比较浅,一直认为只能简单的当一个webView来使用,具体很多细节都忽略,如果想看我之前UIWebView ...

  7. iOS与JS交互的4种方法

    iOS与JS交互的方法: 1.拦截url(适用于UIWebView和WKWebView) 2.JavaScriptCore(只适用于UIWebView,iOS7+) 3.WKScriptMessage ...

  8. UIWebView、WKWebView使用详解及性能分析

    一.整体介绍 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且 ...

  9. iOS OC与JS交互(WebView监听事件)

    在iOS应用的开发过程中,我们经常会使用到WebView,当我们对WebView进行操作的时候,有时会需要进行源生的操作.那么我记下来就与大家分享一下OC与JS交互. 首先先说第一种方法,并没有牵扯O ...

最新文章

  1. easy-mock写的一个简单的模拟二页的反馈
  2. wince注册表结构
  3. C++命名空间namespace
  4. github emoji 表情列表
  5. 机器学习初学者公众号下载资源汇总(一)
  6. ffmpeg加环境变量
  7. junit测试线程_一个在自己的线程中运行测试的JUnit规则
  8. BP神经网络算法学习
  9. semantic ui中文文档_Vuetify-广受欢迎的Material风格的开源UI框架
  10. 集字卡v4.3.4微信公众号原版三种UI+关键字卡控制+支持强制关注
  11. ES6快速入门——类与对象
  12. 转:FileReader详解与实例---读取并显示图像文件
  13. 【图像处理】【去模糊】代码资源汇总
  14. linux版flash下载工具,Linux系统下安装Flash浏览器插件的方法
  15. MAC欺骗-通过思科模拟器实现
  16. matlab实例一之Forward Collision Warning Using Sensor Fusion (视觉和毫米波雷达)
  17. wordpress插件Imagepaste的命名规则修改(一款 直接复制粘贴图片自动上传的编辑器增强插件)
  18. 服务器启动显示按f1f2f10,电脑开机提示按f1f2f5 电脑开机要按F1F2F5
  19. 如何获取本地IP(收藏)
  20. Excel的规划求解实例

热门文章

  1. 微信小程序错误:Expecting 'EOF','}',':',',',']', got INVALID
  2. 矩阵图有何用处?XMind完美展示多对多对象间的关系!
  3. python是一种语言阅读答案_Python是一种________语言。
  4. kmeans聚类算法python实例
  5. 无法解析该计算机名称,敬业签电脑版软件提示“未能解析此远程名称”如何解决?...
  6. 《阴阳师》桃花妖在哪打
  7. GCC编译优化应用预编译头
  8. i7台式电脑配置推荐_i7组装电脑配置清单【攒机之家】
  9. java linkedlist 节点_JAVA学习-LinkedList详解
  10. javaScript 合并对象的多种方式