标签:
项目中经常会出现需要native和web交互的地方,我推荐两种方法。一种是通过JavaScriptCore,一种是通过拦截网络请求的方式
第一种方式
1、先介绍几个名词:
2、先来看个html
<html> <head> <meta charset="UTF-8"> <script> var callShare = function() { var shareInfo = JSON.stringify({"title": "标题", "desc": "内容", "shareUrl": "http://www.baidu.com","shareIco":"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png"}); HH.shareToObjc(shareInfo); } var picCallback = function(photos) { alert(photos); } var shareCallback = function() { alert(‘success‘); } </script> </head> <body> <h1>Objective-C和JavaScript交互的那些事</h1> <div> <input type="button" value="调用相册" onclick="HH.callCamera()"> </div> <div> <input type="button" value="分享字符串" onclick="callShare()"> </div> </body> </html>
从Html中的JavaScript函数 HH.shareToObjc(shareInfo) 函数指向了native方法
3、看个native文件
#import "ViewController.h" #import <JavaScriptCore/JavaScriptCore.h> @protocol JSObjcDelegate <JSExport> /** * 调用相册 */ - (void)callCamera; /** * 分享字符串 * * @param shareString 字符串 */ - (void)shareToObjc:(NSString *)shareString; @end @interface ViewController ()<UIWebViewDelegate,JSObjcDelegate> @property (nonatomic,strong) JSContext *jsContext; @property (weak, nonatomic) IBOutlet UIWebView *webView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"]]; [self.webView loadRequest:[NSURLRequest requestWithURL:url]]; } #pragma mark UIWebViewDelegate - (void)webViewDidFinishLoad:(UIWebView *)webView { self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext[@"HH"] = self; self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) { NSLog(@"异常信息:%@",exception); }; } #pragma mark JSObjcDelegate - (void)shareToObjc:(NSString*)shareString { NSLog(@"%@",shareString); [self.jsContext[@"shareCallback"]callWithArguments:nil]; } - (void)callCamera { JSValue* picCallback = self.jsContext[@"picCallback"]; [picCallback callWithArguments:@[@"图片"]]; } @end
自定义JSObjcDelegate协议,而且此协议必须遵守JSExport这个协议,自定义协议中的方法就是暴露给web页面的方法。在webView加载完毕的 时候获取JavaScript运行的上下文环境,然后再注入桥梁对象名为HH,承载的对象为self即为此控制器,控制器遵守此自定义协议实现协议中对应的方法。在JavaStript调用完本地应用的方法做完相对应的事情之后,又回调了JavaStript中对应的方法,从而实现了web页面和本地应用之间的通讯。
第二种方式
1、在JavaScript代码中使用 window.location.href = "HH://"; //自定义协议
2、在Native中使用以下代码来拦截网络请求
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *url = request.URL.absoluteString; if ([url rangeOfString:@"HH://"].location != NSNotFound) { NSLog(@"callCamera"); return NO; } return YES; }
拦截到网络请求之后对不通的自定义协议进行分发处理,但是这样就无法通过回调的方式调用JavaScript中的回调函数了,可以通过调用stringByEvaluatingJavaScriptFromString函数将数据传递给JavaScript达到相同的效果
标签:
原文地址:http://www.cnblogs.com/guobo2016/p/5162566.html