HyBrid探索(一)

UIWebView加载网页内容

可以通过本地文件、url等方式。

1NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 2NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]; 3[self.webView loadRequest:request];

Native调用JavaScript

Native调用JS是通过UIWebView的stringByEvaluatingJavaScriptFromString 方法实现的,该方法返回js脚本的执行结果。

[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];

实际上就是调用了网页的Window下的一个对象。如果我们需要让native端调用js方法,那么这个js方法必须在window下可以访问到。

JavaScript调用Native

反过来,JavaScript调用Native,并没有现成的API可以调用,而是间接地通过一些其它手段来实现。UIWebView有个代理方法:在UIWebView内发起的任何网络请求都可以通过delegate函数在Native层得到通知。由此思路,我们就可以在UIWebView内发起一个自定义的网络请求,通常是这样的格式:jsbridge://methodName?param1=value1&param2=value2...

在UIWebView的delegate函数中,我们判断请求的scheme,如果request.URL.scheme是jsbridge,那么就不进行网页内容的加载,而是去执行相应的方法。方法名称就是request.URL.host。参数可以通过request.URL.query得到。

问题来了??

发起这样1个网络请求有2种方式。1:location.href .2:iframe。通过location.href有个问题,就是如果js多次调用原生的方法也就是location.href的值多次变化,Native端只能接受到最后一次请求,前面的请求会被忽略掉。

使用ifrmae方式,以调用Native端的方法。

1var iFrame; 2iFrame = document.createElement("iframe"); 3iFrame.style.height = "1px"; 4iFrame.style.width = "1px"; 5iFrame.style.display = "none"; 6iFrame.src = url; 7document.body.appendChild(iFrame); 8setTimeout(function(){ 9iFrame.remove(); 10},100);

举个🌰:

需求:

原生端提供一个UIWebView,加载一个网页内容。还有1个按钮,按钮点击一下网页增加一段段落文本。网页上有2个输入框,用户输入数字,点击按钮,js将用户输入的参数告诉native端,native去执行加法,计算完成后将结果返回给js

1//index.html 2 3 4<html> 5<head> 6<meta http-equiv="Content-Type" content="text/html; charset=utf8"> 7<script language="javascript"> 8function loadURL(url){ 9var iFrame; 10iFrame = document.createElement("iframe"); 11iFrame.style.height = "1px"; 12iFrame.style.width = "1px"; 13iFrame.style.display = "none"; 14iFrame.src = url; 15document.body.appendChild(iFrame); 16setTimeout(function(){ 17iFrame.remove(); 18},100); 19} 20 21 22function receiveValue(value){ 23alert("从原生拿到加法结果为:"+value); 24} 25 26function check() { 27var par1 = document.getElementById("par1").value; 28var par2 = document.getElementById("par2").value; 29loadURL("JSBridge://plus?par1=" + par1 +"&par2=" + par2); 30} 31 32</script> 33</head> 34 35<body> 36<input type="text" placeholder="请输入数字" id="par1"> + <input type="text" placeholder="请输入数字" id="par2"> 37<input type="button" value="=" onclick="check()" /> 38</body> 39</html> 40 41 42 43//ViewController.m 44 45-(void)addContentToWebView{ 46NSString *jsString = @" var pNode = document.createElement(\"p\"); pNode.innerText = \"我是由原生代码调用js后将一段文件添加到html上,也就是注入\";document.body.appendChild(pNode);"; 47[self.webView stringByEvaluatingJavaScriptFromString:jsString]; 48} 49 50 51-(NSInteger)plusparm:(NSInteger)par1 parm2:(NSInteger)par2{ 52return par1 + par2; 53} 54 55 56#pragma mark -- UIWebViewDelegate 57- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ 58NSURL *url = request.URL; 59NSString *scheme = url.scheme; 60NSString *method = url.host; 61NSString *parms = url.query; 62NSArray *pars = [parms componentsSeparatedByString:@"&"]; 63NSInteger par1 = [[pars[0] substringFromIndex:5] integerValue]; 64NSInteger par2 = [[pars[1] substringFromIndex:5] integerValue]; 65if ([scheme isEqualToString:@"jsbridge"]) { 66//发现scheme是JSBridge,那么就是自定义的URLscheme,不去加载网页内容而拦截去处理事件。 67 68if ([method isEqualToString:@"plus"]) { 69NSInteger result = [self plusparm:par1 parm2:par2]; 70[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"receiveValue(%@);",@(result)]]; 71} 72 73return NO; 74} 75return YES; 76} 77

同步和异步问题

js调用native是通过在一个网页上插入一个iframe,这个iframe插入完了就完了,执行的结果需要native另外调用stringByEvaluatingJavaScriptString 方法通知js。这明显是1个异步的调用。而stringByEvaluatingJavaScriptString方法会返回执行js脚本的结果。本质上是一个同步调用

所以js call native是异步,native call js是同步。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

swap空间的增减方法

(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap