Swift-WKWebView与JavaScript的细节,H5页面跳转原生界面
2017-07-04 12:02
344 查看
大家(也包括我)要学会 明白一件事情(注意断句,哈哈)。优秀的程序猿会将问题简单化。
世界上有10种人,一种是先把问题复杂化,然后在一点点的做减法;另一种是先把问题简单化,然后在慢慢的做加法;(好了该进入正题了哈哈!) 文中有源码地址
一,加载HTML的几种方式
Native和js交互没有想象中那么不着边际
二,UIWebView与JS交互
首先使用到
然后通过
在然后就可以在
不要忘记在
最后在
打印信息如下
三,WKWebView与JS交互
1,
wk的交互需要用到
在JS中调用如下方法可以将信息传递到OC的
打印信息如下
源码-地址
四,其他粗暴的方法
在Native和js交互肯定是需要一个桥梁,在UIWebView中使用的是下面这个方法
在WKWebView中使用的是
这两个方法是有返回值的,返回值就是html5页面中 element的value(可以片面的理解为UILable的text),虽然这个方法能执行JavaScript的代码,但只局限为可操作的一些元素和方法,这里给大家解释一下js一些简单的方法
在h5页面加载完成后,执行以下操作
*效果如下,其中 index-kw 是百度收索框的元素 id,给这个id的value,赋值。出现如下效果
这就是一个简单的交互*
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/04/84be2945d3154199884bc54c24cfa378)
但在实际开发中可能需要一些更高级的交互,这里没有使用网上的一些框架
五,其他的交互机制–拦截机制
======H5页面跳转原生界面======
1,项目配置
在 info 里面 添加 URL Schemes
我在里添加的是
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/04/e91e001a9347a6db0722aabe904e9b3c)
然后在 appDegelate.m 中,监听
2,第一种 事件触发
然后在浏览器中输入 com.sir.pppig://, 就可以打开APP了,
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/04/211616b0a02a6c800bb41d58e6769b8c)
点击 open ,打开APP,
![](https://oscdn.geek-share.com/Uploads/Images/Content/201707/04/510b9d5ac14798e5e899f80c73cc7cd9)
3,第二种事件触发
在h5页面触发,
开发中可能会遇到这样的需求:从Native跳转到H5页面需要将用户信息传递或者携带过去!!!有没有遇到过。反正我是遇到过!
遇到这样的需求,是需要结合实际情况的。
如果移动端后台和h5(PC端)用的同一个Web项目,那么实现这个效果不难,一般用sessionId或者是UserId来标识用户,作为用户的识别码。如果他们在同一个后台项目,那么在跳转到h5页面时,可以将 sessionId或者是UserId 以参数的形式传递过去(可以理解为GET请求,但是要注意安全性),那么可以在h5页面得到用户信息
如果 移动端后台和h5(PC端)用的不是同一个Web项目,那么实现起来难,而且效率低,这里不说明!
有时候用户在webView上的数据希望能保留一段时间,那么可以让h5的开发人员,做一下localStorage或者cookie技术!!!
世界上有10种人,一种是先把问题复杂化,然后在一点点的做减法;另一种是先把问题简单化,然后在慢慢的做加法;(好了该进入正题了哈哈!) 文中有源码地址
一,加载HTML的几种方式
/** * 1,加载网络html */ NSString * surl = @"http://192.168.3.134:7080/toCompanyTouch"; NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:surl]]; [self.wkwebView loadRequest:request]; /** * 2,加载本地html 资源(内容) */ NSURL * url =[[NSBundle mainBundle] URLForResource:@"testH5" withExtension:@"html"]; NSString *path = [[NSBundle mainBundle] pathForResource:@"testH5" ofType:@"html"]; NSString * htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; [self.wkwebView loadHTMLString:htmlString baseURL:url]; /** * 3,加载本地html url */ NSURL * url2 =[[NSBundle mainBundle] URLForResource:@"testH5" withExtension:@"html"]; [self.wkwebView loadFileURL:url2 allowingReadAccessToURL:url2];
Native和js交互没有想象中那么不着边际
二,UIWebView与JS交互
首先使用到
<JavaScriptCore/JavaScriptCore.h>框架中的
JSContext,
JSExport对象。
JSContextNative和JS交互时,连接两者的上下文,
JSExportNative和JS交互协议。(实现方法调用时必须实现的协议)
然后通过
KVC的方式获得
JSContext(上线时可能有风险,还可以通过KVO的方式获得)
- (void)webViewDidFinishLoad:(UIWebView *)webView { JSContext * context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // self 是装有 UIWebView的控制器,并且它遵守了 JSExport 协议 //把self这个对象放到上下文中,通过VC这个key可以找到self这个对象 [context setObject:self forKeyedSubscript:@"VC"]; }
在然后就可以在
JS页面中使用这个
VC了,
VC能对应上
OC中那个
controller
不要忘记在
UIViewController中遵守并实现
JSExport
//遵守协议 @protocol JS_OCCOnnectProtocolInWeb <JSExport> - (void)testLog:(NSDictionary*)dict; @end @interface UIWeb_VC () <UIWebViewDelegate,JS_OCCOnnectProtocolInWeb> @property UIWebView * webView; @end @implementation UIWeb_VC //实现协议方法 - (void)testLog:(NSDictionary*)dict { NSLog(@"---testLog--"); NSLog(@"dict=[%@]",dict); } @end
最后在
js中调用就方便了
<button onclick="VC.testLog({'page':'testVC'})">UIWeb测试</button>
打印信息如下
2017-12-06 15:18:58.645195+0800 TestHybriod[2378:1026324] ---testLog-- 2017-12-06 15:18:58.646071+0800 TestHybriod[2378:1026324] dict=[{ page = testVC; }]
三,WKWebView与JS交互
1,
WebKit中
WKWebView使用的是
Safari的浏览器内核,在性能上高于
UIWebView。
wk的交互需要用到
MessageHandler,在实例化
WKWebView时配置一下
WKUserContentController,并且遵守
WKScriptMessageHandler协议实现他的方法
- (void)viewDidLoad { [super viewDidLoad]; WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc]init]; config.userContentController =[[WKUserContentController alloc]init]; //意思是将名字为 ocWkModth 的方法注册到js中 [config.userContentController addScriptMessageHandler:self name:@"ocWkModth"]; self.wkwebView = [[WKWebView alloc]initWithFrame:self.view.boundsconfiguration:config]; }
WKScriptMessageHandler协议的方法。在这里可以接收到
js传来的参数
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSLog(@"body=[%@]",message.body); NSLog(@"name=[%@]",message.name); NSLog(@"frameInfo.absoluteString=[%@]",message.frameInfo.request.URL.absoluteString); }
在JS中调用如下方法可以将信息传递到OC的
WKScriptMessageHandler协议方法中
<a class="test-btn" onclick="window.webkit.messageHandlers.ocWkModth.postMessage({'page':'testVC','result':'success'})">测试</a>
打印信息如下
2017-12-06 14:24:47.955640+0800 TestHybriod[2047:784478] body=[{ page = testVC; result = success; }] 2017-12-06 14:24:47.955845+0800 TestHybriod[2047:784478] name=[ocWkModth]
源码-地址
四,其他粗暴的方法
在Native和js交互肯定是需要一个桥梁,在UIWebView中使用的是下面这个方法
webView.stringByEvaluatingJavaScript(from: "document.getElementById('index-kw').value = '1234';");
在WKWebView中使用的是
webView.evaluateJavaScript("document.getElementById('index-kw').value = '1234abcd';") { (any, err) -> Void in NSLog("any=" + (any as! String)); } /*其实就是这个样子的,后面是swift的闭包*/ webView.evaluateJavaScript("document.getElementById('index-kw').value = '1234abcd';", completionHandler: nil);
这两个方法是有返回值的,返回值就是html5页面中 element的value(可以片面的理解为UILable的text),虽然这个方法能执行JavaScript的代码,但只局限为可操作的一些元素和方法,这里给大家解释一下js一些简单的方法
/*通过这个id可以得到某个元素或者标签*/ var lable_btn = document.getElementById('某个元素或者标签的id'); /*可以set和get元素或者标签的value*/ lable_btn.value = 'value的值'; /*通过这个ClassName可以得到某个元素或者标签 的数组*/ var nodesInput = document.getElementsByClassName('input'); nodesInput[0].value = 'test';
在h5页面加载完成后,执行以下操作
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { webView.evaluateJavaScript("document.getElementById('index-kw').value = '1234';", completionHandler: nil); /*其实就是这个样子的,后面是swift的闭包*/ webView.evaluateJavaScript("document.getElementById('index-kw').value = '1234abcd';") { (any, err) -> Void in /*any 其实就是返回值*/ NSLog("any=" + (any as! String)); } }
*效果如下,其中 index-kw 是百度收索框的元素 id,给这个id的value,赋值。出现如下效果
这就是一个简单的交互*
但在实际开发中可能需要一些更高级的交互,这里没有使用网上的一些框架
/*这里可以监听和拦截 h5 页面的 alert*/ func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { if message == "商量好的信息" { /*这里可以谈一个native的弹窗*/ //UIAlertController .... } }
五,其他的交互机制–拦截机制
======H5页面跳转原生界面======
1,项目配置
在 info 里面 添加 URL Schemes
我在里添加的是
com.sir.pppig
然后在 appDegelate.m 中,监听
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { NSLog(@"----]"); if (!url) { return NO; } // 可以在这里处理打开APP后的 业务逻辑 NSLog(@"new url= [%@]", url); return YES; }
2,第一种 事件触发
然后在浏览器中输入 com.sir.pppig://, 就可以打开APP了,
点击 open ,打开APP,
3,第二种事件触发
在h5页面触发,
<div> <h1>测试页面</h1> <a id="openApp" href="com.sir.pppig://" style="border-radius: 0.05rem; display:block;margin:0 auto;padding:.1rem;color:#fff;background:#f07a0e;width:1.2rem;margin-bottom:.2rem;">打开APP</a > <script> document.getElementById('openApp').onclick = function (e) { /* location.href = 'com.sir.pppig://'; setTimeout(function() { location.href = '/toAppMobilePageTouch'; }, 250); setTimeout(function() { location.reload(); }, 1000); */ /* var ifr = document.createElement('iframe'); ifr.src = 'com.sir.pppig://'; ifr.style.display = 'none'; document.body.appendChild(ifr); setTimeout(function(){ document.body.removeChild(ifr); }, 3000); */ } </script> </div>
开发中可能会遇到这样的需求:从Native跳转到H5页面需要将用户信息传递或者携带过去!!!有没有遇到过。反正我是遇到过!
遇到这样的需求,是需要结合实际情况的。
如果移动端后台和h5(PC端)用的同一个Web项目,那么实现这个效果不难,一般用sessionId或者是UserId来标识用户,作为用户的识别码。如果他们在同一个后台项目,那么在跳转到h5页面时,可以将 sessionId或者是UserId 以参数的形式传递过去(可以理解为GET请求,但是要注意安全性),那么可以在h5页面得到用户信息
如果 移动端后台和h5(PC端)用的不是同一个Web项目,那么实现起来难,而且效率低,这里不说明!
有时候用户在webView上的数据希望能保留一段时间,那么可以让h5的开发人员,做一下localStorage或者cookie技术!!!
相关文章推荐
- JavaScript调用App原生代码(iOS、Android)通用解决方案 实际场景 场景:现在有一个H5活动页面,上面有一个登陆按钮,要求点击登陆按钮以后,唤出App内部的登录界面,当登录成功
- webview加载H5页面使用本界面且可以点击(浏览器不会跳转)
- Swift中使用presentViewController跳转页面后模拟器显示黑屏问题
- javascript - windows打开界面/跳转页面 几种方式和区别
- android原生WebView打开h5页面加载显示不完整错乱问题
- iOS学习之驾照题库(练习页面跳转,传值,UITableView,原生json解析)
- Android原生webView加载h5页面出现加载错乱不完全问题
- [swift]-使用JavaScript解决WKWebView无法发送POST参数问题
- WebViewJavascriptBridge(H5与原生交互)
- Android 以webview的方式集成Dcloud 5+SDK 实现携带数据跳转原生界面
- swift下viewcontroller跳转和关闭当前页面
- H5 跳转web view固定页面
- 利用runTime实现UIWebView 与 JS 随意交互,JS跳转原生页面,亦可实现推送界面万能动态跳转
- ios 判断当前页面从哪个页面跳转过来的(上个界面是哪个ViewController)
- 从h5网站页面跳转到微信小程序——微信web-view高级用法9
- WebView跳转H5页面后无法交互问题
- iOS与H5交互 H5与App原生交互,一般会是前端页面中的JavaScript与App使用的原生开发语言的交互。技术方案应能达到以下要求: 在js与原生进行交互的时候能保证正常的正向调用逻辑返回
- 关于React Native 跳转到原生页面界面详解
- Android中WebView点击事件的拦截跳转到原生的界面
- 使用WebView控件时,H5页面跳转后返回键处理