iOS js交互

来源:互联网 发布:macbookair删除软件 编辑:程序博客网 时间:2024/06/14 08:52

app中嵌套网页是相当一部分app所采用的方式,嵌套网页自然有其优缺之处,这里就不在做讨论

下面介绍一下iOS中js交互的几种方法

从调用者分为 iOS 调用js的方法 和 js 调用iOS的方法两个

在UIWebView中 iOS调用js的方法实现起来相信许多的童鞋都可以做到

不过还是把方法摘出来,供一些没有接触过的朋友看一下

<span style="font-size:14px;">// 方法:</span>
<span style="font-size:14px;">- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;</span>
<span style="font-size:14px;">// 使用:</span>
<p class="p1"><span style="font-size:14px;"><span class="s1">[webView </span><span class="s2">stringByEvaluatingJavaScriptFromString</span><span class="s1">:</span><span class="s3">@"这里写js 中调用的方法"</span><span class="s1">];</span></span></p><span style="font-size:14px;"></span>
话句话来说也就是 stringByEvaluatingJavaScriptFromString:  后面的字符串就是js中要执行的语句

例如:在js中有这样一个方法 

<span style="font-size:14px;">var changeColor= function(color){      document.bgColor = color;  }</span>
那我们就可以使用

[webView stringByEvaluatingJavaScriptFromString:@"changeColor('cyan')"];


改变背景色


怎么是js可以调用iOS中的方法呢?

第一种方法就是通过webView 的代理方法

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    return YES;}


根据request 我们可以得到具体的请求网址,所以我们可以将将要执行的方法或传出的参数放在URL中

但是前提是需要跟写js 的同志提前定义好字段

例如:

"CustomSchme:cmd:param1,param2"

CustomSchme是我们定义用来区别于其他的URL,只要检测到有这个字段,我们就知道这是js要调用iOS的方法了
cmd -- 对应将要执行的方法名

param1,param2 这两个就是参数了。

使用的时候可以通过url 获取到

<pre name="code" class="objc">-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    NSString *requestString = [[request URL] absoluteString];    NSArray *components = [requestString componentsSeparatedByString:@":"];    if ([components count] > 1 && [(NSString *)[components objectAtIndex:0] isEqualToString:@"CustomSchme"]) {        SEL selector = NSSelectorFromString(components[1]);        NSString * param1 = [[[components lastObject] componentsSeparatedByString:@","] firstObject];        NSString * param2 = [[[components lastObject] componentsSeparatedByString:@","] objectAtIndex:1];    }    return YES;}



这样就实现了iOS 和 js 中的相互调用与传值


难道就这样麻烦吗?

NO!

苹果在iOS7之后 引入了  JavaScriptCore 这个库

使用的时候只需要导入  JavaScriptCore 就可以使用


然后在要使用的文件中 添加 

#import <JavaScriptCore/JavaScriptCore.h>

主要使用的就是 JSContext 类

一个JSContext对象,就类似于Js中的window,只需要创建一次即可。

可以在  webView 的代理方法

- (void)webViewDidFinishLoad:(UIWebView *)webView 

中进行初始化

<pre name="code" class="objc">- (void)webViewDidFinishLoad:(UIWebView *)webView {self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];}


接下来就可以将 js 的模型和iOS的模型进项关联,可以想象,如果将 两个模型关联起来之后一切将变得非常清晰

实现:

一个oc的对象在遵守JSExport 协议之后就可以进行转换了

所以我们先自定义一个协议

<pre name="code" class="objc">@protocol CustomDelegate <JSExport>// 这里面我们可以自定义一些方法// 如:// js 调用oc的弹框-(void)alertWith:(NSString*)title message:(NSString*)message;// 当然还可以定义更多的方法/** *  。。。。。。。。 */@end


然后建立一个遵守自定义协议的模型

<span style="font-size:14px;">@interface CustomModel : NSObject<CustomDelegate>@end@implementation CustomModel-(void)alertWith:(NSString*)title message:(NSString*)message btnTitle:(NSString *)btnTitle{    // 这里可以调用系统的弹框}@end</span>


模型建好了,下面就是如何关联


在 js 中可以这样写

<input type="button" value="Call OC to alert" onclick="OCModel.alertWithMessageBtnTitle('This is title','This is message','btnTitle')"></span>

在 iOS 这样写

<pre name="code" class="objc">- (void)webViewDidFinishLoad:(UIWebView*)webView {self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];  CustomModel * model = [[CustomModel alloc]init];    self.jsContext[@"OCModel"] = model;//绑定


<span style="font-size: 14px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">这样就成功的将OC 的 CustomModel 跟 OCModel 关联起来</span>

【注意】

1.在js代码中的OCModel 只是我们定义的一个名字,所以你可以将其改为任何你喜欢的名字,但是在OC代码的绑定中,也要跟你定义的名字一致

2.

<span style="font-size:14px;">alertWithMessageBtnTitle('This is title','This is message',<span style="font-family: Arial, Helvetica, sans-serif;">'btnTitle'</span>)</span>
<span style="font-size:14px;">等价于</span>
<span style="font-size:14px;">alertWith:@"This is title" message:@"This is message" btnTitle:@"btnTitle"</span>
这样就实现了在js中调用OC的方法


但是怎么实现OC调用JS呢?

1.还可用用 [webView stringByEvaluatingJavaScriptFromString:] 这个

2.可以用 JSContext

例如:

<span style="font-size:14px;">js代码:传入一个参数,并将参数在返回去</span>
<span style="font-size:14px;">function back(argument){      return argument;  }</span>


<span style="font-size:14px;">OC 中 通过 jsContext 调用 <span style="font-family: Arial, Helvetica, sans-serif;">evaluateScript: 。。。后面的参数依然是js要执行的代码</span></span>
<span style="font-family:Arial, Helvetica, sans-serif;font-size:14px;">这个时候有返回值的话,会返回一个JSValue 类型的对象</span>
<span style="font-size:14px;">JSValue * value = [self.jsContext evaluateScript:@"back('hello world')"];NSLog(@"%@",[value toObject]);</span>

JSValue 类型的对象正式 JS 与 OC的一个中间对象

例如:

<span style="font-size:14px;">// 将OC对象转换为JSValue</span>
<span style="font-size:14px;">+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context;</span>
<span style="font-size:14px;">// 将bool转换为JSValue+ (JSValue *)valueWithBool:(BOOL)value inContext:(JSContext *)context;</span>
<span style="font-size:14px;">// 将double转换为JSVlaue</span>
<span style="font-size:14px;">+ (JSValue *)valueWithDouble:(double)value inContext:(JSContext *)context;</span>
<span style="font-size:14px;"></span>
<span style="font-size:14px;"></span>
<span style="font-size:14px;">同样</span>
<span style="font-size:14px;">// JSValue 转化为 OC对象</span>
<p class="p1"><span style="font-size:14px;"><span class="s1">- (</span><span class="s2">id</span><span class="s1">)toObject;</span></span></p><p class="p1"><span class="s1"><span style="font-size:14px;">// JSValue 转换为Bool类型</span></span></p><p class="p1"><span style="font-size:14px;"><span class="s1">- (</span><span class="s2">BOOL</span><span class="s1">)toBool;</span></span></p><p class="p1"><span class="s1"><span style="font-size:14px;">// JSValue 转化为Double</span></span></p><p class="p1"><span style="font-size:14px;"><span class="s1">- (</span><span class="s2">double</span><span class="s1">)toDouble;</span></span></p><span style="font-size:14px;"></span>


通过上面的方法就可以实现JS 与 OC 之前的调用

一个简单的Demo











0 0
原创粉丝点击