iOS与网页JS交互
随着移动app的快速迭代开发趋势,越来越多的app中嵌入了html网页,但在一些大中型app中,尤其是电商类app,html页面已经不仅仅满足展示功能,这时html要求能与原生语言进行交互、相互传值。比如携程app中一个热门景点的网页中,点击某个景点,可以跳转到原生中的该景点详情页控制器。
为此,我整理了三种最常用最便捷有效的oc与js交互的方式,供大家学习交流。
第一种:js给oc传值。
1. 技术方案:使用javascriptcore.framework框架
2. 使用场景: 网页中代码中的某个方法,比如点击事件方法,将该方法的参数传值给oc,供oc使用。
比如:携程app中一个热门景点的网页中,有很多个热门景点,点击某个景点的图片或名称,可以跳转到原生中的该景点详情页控制器。3. 代码实现如下:
oc里要实现的代码:
oc里要实现的代码:
拖入javascriptcore.framework静态库,遵守
uiwebviewdelegate代理协议。
在-webviewdidfinishload:方法里编写如下代码:
- (void)webviewdidfinishload:(uiwebview *)webview{ jscontext *context = [webview valueforkeypath:@"documentview.webview.mainframe.javascriptcontext"]; context[@"passvalue"] = ^{ nsarray *arg = [jscontext currentarguments]; for (id obj in arg) { nslog(@"%@", obj); } }; }
其中 passvalue 是js的函数名,得到的 arg数组 里面为js的 passvalue 函数的参数,即 js要传给oc的参数。
js里要实现的代码:
js里要实现的代码:
function testclick() { var str1=document.getelementbyid("text1").value; var str2=document.getelementbyid("text2").value; passvalue(str1,str2); }
在需要给oc传值的函数里(例如:
testclick())直接调用
passvalue()函数,将值传进去即可。
第二种:js给oc传值。
第二种:js给oc传值。
1. 技术方案:使用自定义url方法,每次点击网页
2. 使用场景: 网页中代码中的某个方法,比如点击事件方法,将该方法的参数传值给oc,供oc使用。
比如:携程app中一个热门景点的网页中,有很多个热门景点,点击某个景点的图片或名称,可以跳转到原生中的该景点详情页控制器。3. 代码实现如下:
js里要实现的代码:
js里要实现的代码:
function testclick() { var str1=document.getelementbyid("text1").value; var str2=document.getelementbyid("text2").value; // "objc://"为自定义协议头; // str1&str2为要传给oc的值,以":/"作为分隔 window.location.href="objc://"+":/"+str1+":/"+str2; }
在需要给oc传值的函数里(例如:
testclick())写如上格式的代码。
其中
objc:// 是自定义的协议头,
str1与
str2为js要传给oc的值。
oc里要实现的代码:
oc里要实现的代码:
//遵守uiwebviewdelegate代理协议。 -(bool)webview:(uiwebview *)webview shouldstartloadwithrequest:(nsurlrequest *)request navigationtype:(uiwebviewnavigationtype)navigationtype{ //拿到网页的实时url nsstring *requeststr = [[request.url absolutestring] stringbyremovingpercentencoding]; //在url中寻找自定义协议头"objc://" if ([requeststr hasprefix:@"objc://"]) { // 以"://"为中心将url分割成两部分,放进数组arr nsarray *arr = [requeststr componentsseparatedbystring:@"://"]; nslog(@"%@",arr); //取其后半段 nsstring *paramstr = arr[1]; nslog(@"%@",paramstr); //以":/"为标识将后半段url分割成若*分,放进数组arr2,此时arr2[0]为空,arr2[1]为第一个传参值,arr2[2]为第二个传参值,以此类推 nsarray *arr2 = [paramstr componentsseparatedbystring:@":/"]; nslog(@"%@",arr2); //取出参数,进行使用 if (arr2.count) { nslog(@"有参数"); [self dosomethingwithparama:arr2[1] andparamb:arr2[2]]; }else{ nslog(@"无参数"); } return no; } return yes; } //对js传来的值进行调用 - (void)dosomethingwithparama:(id)parama andparamb:(id)paramb{ nslog(@"%@ %@", parama, paramb); }
第三种:利用第三方库实现js与oc的相互传值。
第三种:利用第三方库实现js与oc的相互传值。
1. 技术方案:使用webviewjavascriptbridge三方库
2. 使用场景: 网页中代码中的某个方法,比如点击事件方法,将该方法的参数传值给oc,供oc使用。
比如:携程app中一个热门景点的网页中,有很多个热门景点,点击某个景点的图片或名称,可以跳转到原生中的该景点详情页控制器。
或者将原生中的用户信息传递给网页,以便其个性化展示3. 代码实现如下:
oc传值给js
oc传值给js
js里需要实现的代码:
js里需要实现的代码:
function setupwebviewjavascriptbridge(callback) { if (window.webviewjavascriptbridge) { return callback(webviewjavascriptbridge); } if (window.wvjbcallbacks) { return window.wvjbcallbacks.push(callback); } window.wvjbcallbacks = [callback]; var wvjbiframe = document.createelement('iframe'); wvjbiframe.style.display = 'none'; wvjbiframe.src = 'wvjbscheme://__bridge_loaded__'; document.documentelement.appendchild(wvjbiframe); settimeout(function() { document.documentelement.removechild(wvjbiframe) }, 0) } //调用上面定义的函数 setupwebviewjavascriptbridge(function (bridge){ //oc传值给js 'testjavascripthandler'为双方自定义好的统一方法名;'data'是oc传过来的值;'responsecallback'是js接收到之后给oc的回调 bridge.registerhandler('testjavascripthandler', function(data, responsecallback) { //打印oc传过来的值 log('objc called testjavascripthandler with', data) var responsedata = { 'javascript says':'right back atcha!' } log('js responding with', responsedata) //给oc的回调 responsecallback(responsedata) })
oc里需要实现的代码:
oc里需要实现的代码:
导入第三方库webviewjavascriptbridge;遵守
uiwebviewdelegate;
//设置第三方bridge是否可用 [webviewjavascriptbridge enablelogging]; //关联webview和bridge _bridge = [webviewjavascriptbridge bridgeforwebview:web]; [_bridge setwebviewdelegate:self]; //oc给js传值,双方自定义一个统一的方法名'testjavascripthandler';data里即为要传过去的值 [_bridge callhandler:@"testjavascripthandler" data:@{@"年龄":@"20"}];
js传值给oc
js传值给oc
js里需要实现的代码:
js里需要实现的代码:
//点击网页上一个按钮时 callbackbt.onclick = function() { var str1=document.getelementbyid("text1").value; var str2=document.getelementbyid("text2").value; //js给oc传值。'passvalue'为双方自定义的统一方法名;'str1'&'str2'为要传的值; response为oc收到后给js的回调 bridge.callhandler('passvalue', {str1,str2}, function(response) { }) }
oc里需要实现的代码:
oc里需要实现的代码:
导入第三方库webviewjavascriptbridge;遵守
uiwebviewdelegate;
//设置第三方bridge是否可用 [webviewjavascriptbridge enablelogging]; //关联webview和bridge _bridge = [webviewjavascriptbridge bridgeforwebview:web]; [_bridge setwebviewdelegate:self]; //js给oc传值.'passvalue'为双方自定义的统一方法名;'data'为js传过来的值;'responsecallback'为oc收到值后给js返回的回调 [_bridge registerhandler:@"passvalue" handler:^(id data, wvjbresponsecallback responsecallback) { //打印js传过来的值 nslog(@"%@", data); //返回给js的值 responsecallback(@"收到了"); }];
需要注意的是:不论哪方给哪方传值,传值的方法名称与对应接收值的方法名称要保持一致。
有任何问题,大家可以在评论区留言,我会一一解答。
下一篇: 机器人产业化以专利为突破口 关注民转军