iOS OC与JS的交互(JavaScriptCore实现)
2016-12-08 19:13
741 查看
随着中秋国庆的到来,公司的运营要搞一系列活动,这就需要服务端提供数据支持,iOS、Android要提供相应的入口及页面进行配合,实现邀请好友分享得奖励的功能。这里面涉及到web端和服务端的交互,web端和iOS、Android的交互,在这仅仅学习下iOS和web的交互。
iOS原生应用和web页面的交互有iOS7之后的JavaScriptCore、拦截协议、第三方框架WebViewJavaScriptBridge、iOS8之后的WKWebView几种方法,这一章我们主要讲解JavaScriptCore和拦截协议这两种办法。WebViewJavaScriptBridge是基于拦截协议进行的封装,使用也不如JavaScriptCore方便本文不做细讲。WKWebView是iOS8之后推出的,还没有成为主流使用,所以本篇文章也不做详细叙述。
Objective-C调用JavaScript代码
用这些方法执行复杂的一大段js代码也是没有必要的,在一些场景下还是比较实用的,比如
JavaScriptCore.html代码解释如下:
Native是iOS本地要注入的一个对象,也就是web页面与原生应用的一个桥接。页面上定义了Native传值、oc原生Alert、Share三个按钮,点击Native传值首先通过Native这个桥梁调用本地的方法- (void)callme:(NSString )string并传入参数;点击oc原生Alert按钮通过 self.context[@”deliverValue”] = ^(NSString message) 的block形式直接调用;点击Share按钮会先调用html本地文件中的JavaScrip的function方法callShare,这里将分享的url参数传给share方法,然后再通过Native桥梁去调用原生应用的本地方法- (void)share:(NSString *)shareUrl,而shareCallBack为分享成功的回调方法,也就是原生方法调用后js的回调方法。
JavaScriptCore中类及协议:
JSContext:给JavaScript提供运行的上下文环境
JSValue:JavaScript和Objective-C数据和方法的桥梁
JSExport:协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议
ViewController中的代码
代码解释:
自定义JSObjectDelegate协议的时候必须遵守JSExport这个协议,这些自定义的协议中的方法是留给web页面的接口方法。在webView加载完毕的时候获取JavaScript运行的上下文环境,然后注入桥接的对象Native,对象self就是此控制器,控制器遵守此自定义协议实现协议中的相对应的方法。当JavaStript调用完原生本地应用的方法后,再回调JavaScript中对应的方法,从而实现了Web页面和原生本地应用之前的通信。
OC调用JS效果图:
JS调用OC代码
JS调用OC效果图:
ps:注意JavaStript调用本地方法是在子线程中执行的,在回调JavaStript方法的时候最好与刚开始调用此方法的线程保持同一个,要考虑线程之间的切换。
拦截协议
html代码解释:
点击changeWindow按钮调用网页callMethod方法,方法的实现是window.location.href改变主窗口的指向,也就是发出一个链接为wjika://changeWindow的请求,从而将内容传递给原生应用,请求中可以传递原生应用需要的参数。在原生应用中我们可以拦截这个请求,根据内容去判断JavaStript想要我们做的事情,这就实现了web页面和原生应用本地之间的交互。
viewController中的代码
在webView的shouldStartLoadWithRequest代理方法中去拦截自定义的协议wjika://如果是此协议则去做JavaStript想要移动端做的事情,调用原生应用的方法,注意协议的头等字段是前端和移动端事先约定好的。
ps:拦截协议适合一些简单的情况,复杂的交互需要相互传递参数的比较麻烦,并且不能回调JavaScript的方法。另外研究拦截协议的朋友可以看看WebViewJavaScriptBridge这个第三方,是对拦截协议的封装。 JavaScriptCore使用起来比较简单,方便web端和移动端的统一。iOS8推出的WKWebView会逐渐成为主流,这个功能更强大。仅供交流学习,欢迎各位同学指正。
Demo下载
参考
iOS中实现JS和OC的交互(Hybrid App)
iOS原生应用和web页面的交互有iOS7之后的JavaScriptCore、拦截协议、第三方框架WebViewJavaScriptBridge、iOS8之后的WKWebView几种方法,这一章我们主要讲解JavaScriptCore和拦截协议这两种办法。WebViewJavaScriptBridge是基于拦截协议进行的封装,使用也不如JavaScriptCore方便本文不做细讲。WKWebView是iOS8之后推出的,还没有成为主流使用,所以本篇文章也不做详细叙述。
Objective-C调用JavaScript代码
// UIWebView的方法 -(NSString*)stringByEvaluatingJavaScriptFromString:(NSString *)script; // JavaScriptCore中JSContext的方法 -(JSValue *)evaluateScript:(NSString *)script; -(JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL
用这些方法执行复杂的一大段js代码也是没有必要的,在一些场景下还是比较实用的,比如
// 获取当前页面的title NSString *title = [webview stringByEvaluatingJavaScriptFromString:@"document.title"]; // 获取当前页面的url NSString *url = [webview stringByEvaluatingJavaScriptFromString:@"document.location.href"];
JavaScriptCore概述
JavaScriptCore这个框架是iOS7之后苹果推出的,方便了开发者的使用,让web页面和iOS本地原生应用交互起来更加简单。web前端
在与前端交互过程中,需要与前端开发人员沟通好传值、方法名等,然后移动端做适配。这里以传值、调用本地alert、分享为例来讲解,用webView加载HTML文件,这里用的是本地HTML名字为JavaScriptCore.html,代码如下:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> 来自html中的jsCallOC标题</title> </head> <body> <div style="margin-top: 20px"> <h2>JavaScript与OC的交互</h2> <input type="button" value="Native传值" onclick="Native.callme('jS开始调用OC本地Native咯')"> </div> <div> <input type="button" value="oc原生Alert" onclick="deliverValue('来自HTML中的Alert信息')"> </div> <div> <input type="button" value="Share" onclick="callShare()"> </div> <script> var alertShowIn = function(str) { alert(str); } var callShare = function() { var shareUrl = "http://image.baidu.com/search/detail?ct=503316480&z=&tn=baiduimagedetail&ipn=d&ie=utf-8&in=24401&cl=2&lm=-1&st=-1&step_word=&rn=1&cs=&ln=1998&fmq=1402900904181_R&ic=0&s=&se=1&sme=0&tab=&width=&height=&face=0&is=&istype=2&ist=&jit=&fr=ala&ala=1&alatpl=others&pos=1&pn=1&word=图片%20动漫卡通&di=0&os=1199087710,2399135616&pi=0&objurl=http%3A%2F%2Fv.flash.beijingww.com%2Fcomic%2Fwallpaper%2Fjiqimao%2F15.jpg" Native.share(shareUrl); } var shareCallBack = function(){ alert('回调js分享success'); } </script> </body> </html>
JavaScriptCore.html代码解释如下:
Native是iOS本地要注入的一个对象,也就是web页面与原生应用的一个桥接。页面上定义了Native传值、oc原生Alert、Share三个按钮,点击Native传值首先通过Native这个桥梁调用本地的方法- (void)callme:(NSString )string并传入参数;点击oc原生Alert按钮通过 self.context[@”deliverValue”] = ^(NSString message) 的block形式直接调用;点击Share按钮会先调用html本地文件中的JavaScrip的function方法callShare,这里将分享的url参数传给share方法,然后再通过Native桥梁去调用原生应用的本地方法- (void)share:(NSString *)shareUrl,而shareCallBack为分享成功的回调方法,也就是原生方法调用后js的回调方法。
iOS移动端
JavaScriptCore中web页面调用原生应用的方法可以用Delegate或Block两种方法。JavaScriptCore中类及协议:
JSContext:给JavaScript提供运行的上下文环境
JSValue:JavaScript和Objective-C数据和方法的桥梁
JSExport:协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议
ViewController中的代码
#import <JavaScriptCore/JavaScriptCore.h> @protocol JSObjectDelegate <JSExport> -(void)callme:(NSString *)string; -(void)share:(NSString *)shareUrl; @end @interface JSCallOCViewController () <UIWebViewDelegate, JSObjectDelegate> @property(nonatomic, strong) UIWebView *webView; @property(nonatomic, strong) JSContext *context; @end @implementation JSCallOCViewController -(void)viewDidLoad { [super viewDidLoad]; self.title = @"js call oc"; self.view.backgroundColor = [UIColor whiteColor]; self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)]; [self.view addSubview:self.webView]; NSString *path = [[NSBundle mainBundle] pathForResource:@"JavaScriptCore" ofType:@"html"]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]; self.webView.delegate = self; [self.webView loadRequest:request]; } #pragma mark - UIWebViewDelegate -(void)webViewDidFinishLoad:(UIWebView *)webView { //获取html title设置导航栏 title self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //捕捉异常回调 self.context.exceptionHandler = ^(JSContext context, JSValue exceptionValue) { context.exception = exceptionValue; NSLog(@"异常信息: %@",exceptionValue); }; //通过JSExport协议关联Native的方法 self.context[@"Native"] = self; //通过block形式关联JavaScript中的函数 __weak typeof(self) weakSelf = self; self.context[@"deliverValue"] = ^(NSString *message) { __strong typeof(self) strongSelf = weakSelf; dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController *alertControl = [UIAlertController alertControllerWithTitle:@"this is a message" message:message preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]; [alertControl addAction:cancelAction]; [strongSelf.navigationController presentViewController:alertControl animated:YES completion:nil]; }); }; } -(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSLog(@"error == %@",error); } #pragma mark - JSExport Methods -(void)callme:(NSString *)string { NSLog(@"%@",string); } -(void)share:(NSString *)shareUrl { NSLog(@"分享的url=%@",shareUrl); JSValue *shareCallBack = self.context[@"shareCallBack"]; [shareCallBack callWithArguments:nil]; }
代码解释:
自定义JSObjectDelegate协议的时候必须遵守JSExport这个协议,这些自定义的协议中的方法是留给web页面的接口方法。在webView加载完毕的时候获取JavaScript运行的上下文环境,然后注入桥接的对象Native,对象self就是此控制器,控制器遵守此自定义协议实现协议中的相对应的方法。当JavaStript调用完原生本地应用的方法后,再回调JavaScript中对应的方法,从而实现了Web页面和原生本地应用之前的通信。
OC调用JS效果图:
JS调用OC代码
-(void)caculateButtonAction:(id)sender { NSNumber *inputNumber = [NSNumber numberWithInteger:[textField.text integerValue]]; JSValue *function = [self.context objectForKeyedSubscript:@"factorial"]; JSValue *result = [function callWithArguments:@[inputNumber]]; resultL.text = [NSString stringWithFormat:@"%@", [result toNumber]]; }
JS调用OC效果图:
ps:注意JavaStript调用本地方法是在子线程中执行的,在回调JavaStript方法的时候最好与刚开始调用此方法的线程保持同一个,要考虑线程之间的切换。
拦截协议
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <div> <input type="button" value="changeWindow" onclick="callMethod()"> </div> <script> function callMethod() { window.location.href = 'wjika://changeWindow'; } </script> </body> </html>
html代码解释:
点击changeWindow按钮调用网页callMethod方法,方法的实现是window.location.href改变主窗口的指向,也就是发出一个链接为wjika://changeWindow的请求,从而将内容传递给原生应用,请求中可以传递原生应用需要的参数。在原生应用中我们可以拦截这个请求,根据内容去判断JavaStript想要我们做的事情,这就实现了web页面和原生应用本地之间的交互。
viewController中的代码
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *url = request.URL.absoluteString; if ([url rangeOfString:@"wjika://"].location != NSNotFound) { // url的协议头是wjika NSLog(@"改变窗口指向"); return YES; } return No; }
在webView的shouldStartLoadWithRequest代理方法中去拦截自定义的协议wjika://如果是此协议则去做JavaStript想要移动端做的事情,调用原生应用的方法,注意协议的头等字段是前端和移动端事先约定好的。
ps:拦截协议适合一些简单的情况,复杂的交互需要相互传递参数的比较麻烦,并且不能回调JavaScript的方法。另外研究拦截协议的朋友可以看看WebViewJavaScriptBridge这个第三方,是对拦截协议的封装。 JavaScriptCore使用起来比较简单,方便web端和移动端的统一。iOS8推出的WKWebView会逐渐成为主流,这个功能更强大。仅供交流学习,欢迎各位同学指正。
Demo下载
参考
iOS中实现JS和OC的交互(Hybrid App)
相关文章推荐
- IOS中 使用JavaScriptCore 实现OC与JS的交互
- IOS中 使用JavaScriptCore 实现OC与JS的交互
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- iOS开发:JavaScriptCore.framework的简单使用--JS与OC的交互篇
- iOS JS 交互之利用系统JSContext实现 JS调用OC方法以及Objective-C调用JavaScript方法
- iOS OC与JS的交互(WebViewJavascriptBridge实现)
- iOS webView的高级用法之JS交互,js与oc的相互调用(JavaScriptCore)
- 使用JavaScriptCore实现OC和JS交互详解
- 转载 【iOS开发】网页JS与OC交互(JavaScriptCore) OC ----->JS
- 系统框架JavaScriptCore实现js和oc交互
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- iOS使用WebViewJavascriptBridge实现OC与JS交互
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- 使用javascriptcore实现oc与js的交互
- iOS 基于JavaScriptCore 不等webView加载完毕就交互,网页获取原生内容。 webView的高级用法之JS交互,js与oc的相互调用
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- [iOS] 使用WebViewJavascriptBridge实现OC与JS交互
- iOS开发使用WebViewJavascriptBridge实现OC与JS交互
- iOS中JS 与OC的交互(JavaScriptCore.framework)