JS与原生OC的三种交互方式
大家在做项目的时候应该也遇到过需要h5与OC之间通信,来实现某种特定的效果,于是我总结一下最近用到过的这两者之间的交互的方式(当然现在还有很多其他的交互方式,比如使用其他第三方的组件等等):
- 通过在UIWebView的代理方法里拦截URL实现
- 通过OC自带的JavaScriptCore.framework来实现
通过ajax方式拦截url来实现
- 首先来说一下目前最常见的第一种方式来实现的方式(通过在UIWebView的代理方法里拦截URL实现),这种方式是在webview代理方法中获取所需要的url,再根据获取的url里规定的特殊字段来进行处理,如下代码:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//第一种交互方式
NSString *urlStr = request.URL.absoluteString;
if ([urlStr rangeOfString:@"baidu"].location!=NSNotFound) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"" message:@"第一种方式" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
[alertView show];
}
return YES;
}
- 然后再说一下JavaScriptCore.framework来实现的方式:首先在UIWebView中用JSContext获取该UIWebView的javascript执行环境,
- 首先来说一下目前最常见的第一种方式来实现的方式(通过在UIWebView的代理方法里拦截URL实现),这种方式是在webview代理方法中获取所需要的url,再根据获取的url里规定的特殊字段来进行处理,如下代码:
_webview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
_webview.backgroundColor = [UIColor lightGrayColor];
_webview.delegate = self;
[self.view addSubview:_webview];
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *localUrl = [[NSURL alloc] initFileURLWithPath:htmlPath];
[_webview loadRequest:[NSURLRequest requestWithURL:localUrl]];
//第二种交互方式
JSContext *context = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"button2Click22"]=^(){
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
if([[NSString stringWithFormat:@"%@",jsVal] isEqualToString:@"duijieyu"])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"" message:@"第二种方式" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
[alertView show];
break;
}
}
JSValue *this = [JSContext currentThis];
NSLog(@"this: %@",this);
};
然后在javascript执行环境中,定义一个相对应的js函数,如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Document</title>
<link href=" " rel="stylesheet"/>
<script src="jquery.js" type="text/javascript"></script>
</head>
<body>
</br></br>
<a href="javascript:;" id="btn2" style="font-size: 18px" onclick="button2Click()">第二种交互方式(JavaScriptCore)</a></br>
<script type="text/javascript">
function button2Click()
{
button2Click22("duijieyu");//oc里捕获的对接语
}
</script>
</body>
</html>
里面相对应的细节需要改成你们自己项目里规定好的细节。
- 然后再说一下同ajax的方式进行通信吧,安卓系统通过ajax进行与h5页面的痛心特别容易,但是如果iOS也想要通过ajax进行与h5交互的话,就可以使用这种方法了(目前我能找到的方法,如果有好的方法,欢迎指教),首先这个方法需要再项目里加一下桥接文件,作为交互的桥梁,然后通过ajax里用规定的好的链接与字段与桥接文件里对应的字段进行转换,最后ViewController通过桥接文件获取相对应的信息进行处理,代码如下:
<script type="text/javascript">
$('#btn3').on('click',function(){
$.ajax({
type : 'get',
url : 'http://myApp.example.org/alert?title=Test%20from%20AJAX&message=this%20is%20a%20message%20from%20an%20AJAX%20request"',
data:'',
dataType : 'json',
timeout : 300,
success:function(data) {
$('#btn').html('点我了');
},
error:function(errMsg) {
$('#btn').html('出错了');
}
})
})
}
#pragma mark - NativeActionDelegate
-(NSDictionary *)handleAction:(NativeAction *)action error:(NSError *__autoreleasing *)error
{
if ([action.action isEqualToString:@"alert"]) {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[action.params objectForKey:@"title"] message:[action.params objectForKey:@"message"] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alertView show];
});
return nil;
}
return nil;
}
注意:大家不要忘了设置桥接文件的代理哦。
附demo地址: