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限制



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

  • WKWebView的使用

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



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


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;




ok>>>>