今天来学一下JS和iOS交互的
下面举个例子
要做出这样的效果
html页面代码
<!DOCTYPE html>
<html>
<body>
<h1 id="id1">I'm Html </h1>
<button type="button" οnclick=clickMe()> Talk To iOS</button>
<script>
<!-- 第一种调用方式-->
function clickMe() {
window.location.href = "Gap:I'm iOS, copy that";
}
</script>
</body>
</html>
从Html发消息到iOS端
先说说html5上的按钮点击window.location.href = "Gap:I'm iOS, copy that";
这样会产生一次请求, 我们就可以截取到链接
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *path=[[request URL] absoluteString];
NSLog(@"%@",path);
if ([path rangeOfString:@"gap:"].location != NSNotFound) {
NSString *str = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
self.iosLabel.text = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
return NO;
}
return YES;
}
从ios端发送到Html
插一段js代码来改变id为“id1”的元素的文字修改掉
- (IBAction)talkToHtmlAction:(id)sender
{
NSString *js = @"var label = document.getElementById('id1'); label.innerText= 'I receive Your Message'";
// NSString *js = @"document.getElementById('id1').innerText='I receive Your Message'";
[self.webView stringByEvaluatingJavaScriptFromString:js];
}
如果事情真的这么简单就好了
下面来说一些比较复杂的
UIWebView发起特殊请求的方式
<!DOCTYPE html>
<html>
<body>
<h1 id="id1">I'm Html </h1>
<button type="button" οnclick=clickMe()> Talk To iOS</button>
<script>
<!-- 第一种调用方式-->
function clickMe() {
<span style="color:#ff0000;"> window.location.href = "Gap:I'm iOS, copy that";</span>
}
</script>
</body>
</html>
这里是通过修改window.location.href(也可以用document.location)来发起一个特殊请求
但是如果你需要2次修改window.location.href那会怎么样呢 ?只有后面的那句才有用
function clickMe() {
window.location.href = "http://www.w3school.com.cn";
window.location.href = "Gap:I'm iOS, copy that";
}
那我们该怎么办呢
把clickme()的函数里面的换掉 (参数要用UTF8编码一下)
function clickMe() {
// 简单传值
// var text = "I'm iOS, copy that";
// 传个json字符串过去
var text = '{"length1":76,"length2":155,"length3":76,"length4":155,"length5":76}';
var url = "gap:" + EncodeUtf8(text);
// 顺序很重要
loadURL(url);
//window.location.href = "http://www.w3school.com.cn";
}
function loadURL(url) {
window.location.href=url;
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", url);
iFrame.setAttribute("style", "display:black;");
iFrame.setAttribute("height", "100px");
iFrame.setAttribute("width", "100px");
iFrame.setAttribute("frameborder", "10");
document.body.appendChild(iFrame);
// 发起请求后这个iFrame就没用了,所以把它从dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
function EncodeUtf8(s1)
{
// escape函数用于对除英文字母外的字符进行编码。如“Visit W3School!”->"Visit%20W3School%21"
var s = escape(s1);
var sa = s.split("%");//sa[1]=u6211
var retV ="";
if(sa[0] != "")
{
retV = sa[0];
}
for(var i = 1; i < sa.length; i ++)
{
if(sa[i].substring(0,1) == "u")
{
retV += Hex2Utf8(Str2Hex(sa[i].substring(1,5)));
if(sa[i].length>=6)
{
retV += sa[i].substring(5);
}
}
else retV += "%" + sa[i];
}
return retV;
}
这样子的话既可以web跳界面又可以顺利的和ios交互
如果我想传递一些复杂一点的参数呢
可以直接传个json字符串过去
var text = '{"length1":76,"length2":155,"length3":76,"length4":155,"length5":76}';
var url = "gap:" + EncodeUtf8(text);
loadURL(url);
接收参数的协议里面也要改
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *path=[[request URL] absoluteString];
NSLog(@"%@",path);
if ([path rangeOfString:@"gap:"].location != NSNotFound) {
NSString *str = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *strDic = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
NSData *data = [strDic dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"dic:%@", dic);
self.iosLabel.text = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
return NO;
}
return YES;
}
常见的JS调用
(1)获取标题
NSString *title = [webview stringByEvaluatingJavaScriptFromString:@"document.title"];
(2)获取URL
NSString *url = [webview stringByEvaluatingJavaScriptFromString:@"document.location.href"];
一些注意事项
《参考自ios进阶开发》
同步和异步
UIWebView调用原生界面时是异步操作
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
原生界面调用UIWebView是同步
[self.webView stringByEvaluatingJavaScriptFromString:js];//直接返回NSString
这一点要注意一下
线程阻塞
当oc调用stringByEvaluatingJavaScriptFromString时 可能是由于js是单线程的原因会阻塞js代码的执行
解决办法是js端用defer把iFrame的插入延后执行
主线程问题
由于stringByEvaluatingJavaScriptFromString必须在主线程执行,所以如果主线程执行时间过长就会阻塞UI的更新 我们应该尽量让js的代码执行时间短
第三方库
(1)WebViewJavascriptBridge
https://github.com/marcuswestin/WebViewJavascriptBridge
(2)cordova
http://cordova.apache.org/