JS 与 OC 的交互原来没有好好研究过,用的都是比较简单拦截 Url 的方式,通过定义专用的 Url 来拦截关键字来进行特定处理。但这只能用于简单的传值,进行一些简单的交互。涉及到,JS 调用 OC 方法或者 OC 调用 JS 方法,一些比较复杂的交互逻辑的时候这种方式就显得力不从心了。满足不了我们的需求。当然也有比较好的第三方库如:WebViewJavascriptBridge。但一般系统的方法足够用的时候,就没必要使用第三方库。这样即有利于减小安装包体积,又可以减少第三方的不稳定性等因素的干扰 一、拦截url的方式,进行简单交互在webView的代理方法中处理 这里简单介绍一下 URL 里面的一些属性
NSString
scheme = url.scheme;//协议:http host = url.host;//主机名
NSNumber
port = url.port;//端口号 path = url.path;//一般用来表示主机上的一个目录或文件地址NSString *query = url.query;//参数,发给服务器的参数 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSURL *url = request.URL; if ([url.scheme isEqualToString:@"nanshanyi"]) { //在这里做JavaScript调用Objective-C的事。 //需要传的值放在url后面的参数里如:Nanshanyi://www.php8080.com?{"title":"标题","id":"123","des":"描述内容"} NSString *dataJson = url.query;//拿到后面的json字符串 NSString *str = [dataJson stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSLog(@"%@",str); //执行一段js代码,弹出提示框 [webView stringByEvaluatingJavaScriptFromString:@"alert('seccess')"]; return NO; } return YES; } 二、使用JavaScriptCore实现交互JavaScriptCore是封装了JavaScript和Objective-C桥接的Objective-C API,只需要较少的的代码,就可以实现JavaScript与Objective-C的相互调用。 在iOS7之前,只能通过向UIWebView发送stringByEvaluatingJavaScriptFromString:消息来执行一段JavaScript的脚本。而且如果想用JavaScript来调用Objective-C的方法,必须打开一个自定义的URL(例如:Nanshanyi://),然后在UIWebView的delegate方法webView:shouldStartLoadWithRequest:navigationType中进行处理。也就是上问中提到的方法 JavaScriptCore中类及协议: JSContext:给JavaScript提供运行的上下文环境 JSValue:JavaScript和Objective-C数据和方法的桥梁 JSManagedValue:管理数据和方法的类 JSVirtualMachine:处理线程相关,使用较少 JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议 (1)使用Delegate方式实现先放上js的网页代码,可以建一个HTML文件直接复制进去即可使用 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> </head> <body> <h1>OC和JS的交互代理方式</h1> <div> <!-- 生成一个 button 添加点击事件--> <input type="button" value="JsToOcShare" onclick="callShare()"> </div> <script> function callShare() { var shareContent = JSON.stringify({"title": "分享", "desc": "分享内容", "shareUrl": "http://www.jianshu.com/users/774b1d5616a7/latest_articles"}); Nanshanyi.share(shareContent); } <!-- OC调JS--> function showAlert(message){ alert(message); } <!-- JS调OC成功后回调--> var shareCallback = function(){ alert('success'); } </script> </body> </html> #import <JavaScriptCore/JavaScriptCore.h> @protocol JSObjcDelegate <JSExport> - (void)share:(NSString *)shareContent; @end @interface ViewController : UIViewController<JSObjcDelegate> @end .m文件 #import "ViewController.h" @interface ViewController ()<UIWebViewDelegate> @property (nonatomic,strong)UIWebView *webView; @property (nonatomic,strong)JSContext *jsContext; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self CustomUI]; } - (void)CustomUI{ self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds]; self.webView.delegate = self; [self.view addSubview:_webView]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"untitled3" withExtension:@"html"]; [self.webView loadRequest:[NSURLRequest requestWithURL:url]]; } - (void)webViewDidFinishLoad:(UIWebView *)webView{ _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //代理方式JS调OC方法 //Nanshanyi 相当于桥接,通过它将 OC 与 JS 联系起来 _jsContext[@"Nanshanyi"] = self; _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; NSLog(@"异常信息:%@", exceptionValue); }; } - (void)share:(NSString *)shareContent { NSLog(@"share:%@", shareContent); // 分享成功后,回调js的方法shareCallback // 也即是 OC 调用 JS 方法,只调用方法,没有参数传递 JSValue *shareCallback = self.jsContext[@"shareCallback"]; [shareCallback callWithArguments:nil]; } (2)使用Block方式实现同样放上一段简单的JS <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> </head> <body> <h1>OC和JS的交互Block方式</h1> <div> <input type="button" value="JsToOcShare" onclick="callShare(shareContent)"> </div> <script> var shareContent = JSON.stringify({"title":"分享", "desc":"分享内容", "shareUrl":"http://www.jianshu.com/users/774b1d5616a7/latest_articles"}); function callShare(share) { //share为形参,shareContent为实参,即要传递的参数 } // OC调JS message为传递的参数 function showAlert(message){ alert(message); } </script> </body> </html> WebView代理方法的实现 - (void)showAlert{//直接调用该方法实现OC调用JS,并传参 NSString *jsStr = @"showAlert('ios js交互成功,我是网页 alert')"; [_jsContext evaluateScript:jsStr]; } - (void)webViewDidFinishLoad:(UIWebView *)webView{ _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //block 方式 JS直接调用OC,并传参,简单明了 __weak typeof (self)weakSelf = self; _jsContext[@"callShare"] =^(id obj){ weakSelf.lable.text = obj; //把传过来的Json字符串,转为字典 NSData *data = [(NSString *)obj dataUsingEncoding:NSUTF8StringEncoding ]; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",dict); }; _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; //比如把js中的方法名改掉,OC找不到相应方法,这里就会打印异常信息 NSLog(@"异常信息:%@", exceptionValue); }; } 至此,已经完成了JS与OC的简单交互,实现了JS与OC方法的相互调用,与传值。 (责任编辑:最模板) |