OC&JS交互实例浅析

现在iOS开发中使用的混编情况越来越多了,今天我们就OC与JS的交互来做一下简单的剖析增进了解。我们Demo使用的场景是在webview上展示HTML页面,点击HTML上的按钮进入相册,在相册中选择图片并上传到服务器。我们现在开始进行分析,Demo会在文末给出。


JavaScriptCore简介图.png

一、OC与JS交互中使用方法注释与关联

首先,我们要导入#import <JavaScriptCore/JavaScriptCore.h>,然后我们来熟悉一下里面常见的几个对象及协议。

1、对象注释:

1、JSContext:给JavaScript提供运行的上下文环境,通过-evaluateScript:方法就可以执行一JS代码
2、JSValue:JavaScript和Objective-C数据和方法的桥梁,封装了JS与ObjC中的对应的类型,以及调用JS的API等
3、JSManagedValue:管理数据和方法的类
4、JSVirtualMachine:处理线程相关,使用较少
5、JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议

2、相互之间的关联:

1、JSVirtualMachine为JavaScript的运行提供了底层资源,
2、JSContext为其提供运行环境,通过- (JSValue *)evaluateScript:(NSString *)script;方法就可以执行一段JS脚本,并且其中有方法变量等信息都会被存储在其中以便在需要的时候使用。而JSContext的创建都是基于JSVirtualMachine:- (id)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;,
如果是使用- (id)init;进行初始化,那么在其内部会自动创建一个新的JSVirtualMachine对象然后调用前边的初始化方法。
3、JSValue可以说是JavaScript和OC之间互换的桥梁,它提供了多种
方法可以方便的把JavaScript数据类型转换成Objective-C,或者是转换过去。

知识点链接:http://blog.iderzheng.com/introduction-to-ios7-javascriptcore-framework/

二、HTML内部方法的注释

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
      <title></title>
      </head>
  <body>
    <div>
      <h3>JS与iOS交互</h3>
      <h4>JS页面获取iOS系统图片</h5>
        </div>
    <div>
      <input type = "button" style="width: 50%;height: 5%;" id="Button" value="打开相机获取图片" onclick="getIOSImage()"></button><!--按钮的方法getIOSImage -->
        </div><dir />
    <div>
      <img src="testImage.png" id="changeImage"style="width: 30%; height: 30%;" onclick="getIOSImage()"><!--src="图片的相对路径" 如果把html文件导入工程中,图片路径和OC一样只写图片名字和后缀就可以,(记得要先把图片添加到工程) 图片也可以实现按钮的方法getIOSImage -->
        </div>
    <span id="iosParame" style="width: 200px; height: 50%; color:orangered; font-size:15px" value="等待获取ios参数" >
      </div>
      <script>
        var getIOSImage = function(){//按钮方法getIOSImage中包含代理
          var parameter = {'title':'JS调OC','describe':'这里就是JS传给OC的参数'};
          // 在下面这里实现js 调用系统原生api
          window.iosDelegate.getImage(JSON.stringify(parameter));// 实现数据的 json 格式字符串
        }
      // 这里是 iOS调用js的方法
      function setImageWithPath(arguments){
        document.getElementById('changeImage').src = arguments['imagePath'];
        document.getElementById('iosParame').innerHTML = arguments['iosContent'];
      }
      </script>
      </body>
</html>
效果图.png

三、webView加载HTML方法的使用

  • 处理流程:
    1、创建WebView加载本地HTML文件。
    2、webView加载完成之后代理中进行JS&OC交互。并调用JS中的代理方法,获取代理中的参数getImage。
    3、JS中的按钮连接着代理,只要点击按钮就会调用代理,在代理中有打开相册的的方法beginOpenPhoto
    (JavaStript调用本地方法是在子线程中执行的)。
    4、在OC选择图片的代理中存储图片并将图片上传到HTML页面中。
    5、上传图片到服务器上。

a:设置HTML中的代理以及相关全局变量

@protocol JSDelegate <JSExport>
//这个方法就是window.document.iosDelegate.getImage(JSON.stringify(parameter)); 中的 getImage()方法
- (void)getImage:(id)parameter;
@end

@interface ViewController ()<UIWebViewDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,JSDelegate>{
  int indextNumb;// 交替图片名字
  UIImage *getImage;//获取的图片
}
@property(strong, nonatomic) JSContext *jsContext;
@property(retain, nonatomic) UIWebView *myWebView;
@end

b:创建WebView加载本地HTML文件

- (void)setupWebView{
  if (!self.myWebView) {
    //初始化 WebView
    self.myWebView = [[UIWebView alloc] initWithFrame:self.view.bounds];
    self.myWebView.backgroundColor = [UIColor colorWithRed:1.000 green:1.000 blue:0.400 alpha:1.000];
    // 代理
    self.myWebView.delegate = self;
    NSURL *path = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
    [self.myWebView loadRequest:[NSURLRequest requestWithURL:path]];
    [self.view addSubview:self.myWebView];
  }
}

c:web加载完成开始监听js的方法

- (void)webViewDidFinishLoad:(UIWebView *)webView{
  //1/初始化context
  self.jsContext = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //2、OC调用JS
    //OC用jsContext[@"iosDelegate"] 此种方式捕捉代理
  self.jsContext[@"iosDelegate"] = self;//挂上代理  iosDelegate是window.document.iosDelegate.getImage(JSON.stringify(parameter)); 中的 iosDelegate
  self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){
    context.exception = exception;
    NSLog(@"获取 self.jsContext 异常信息:%@",exception);
  };
}

d:JS中代理调用打开相册的方法

//调用代理,打开相册,然后处理选择的图片 这里可以画出处理的流程
#pragma mark - JSDelegate
- (void)getImage:(id)parameter{
  // 把 parameter json字符串解析成字典
  NSString *jsonStr = [NSString stringWithFormat:@"%@", parameter];
  NSDictionary *jsParameDic = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding ] options:NSJSONReadingAllowFragments error:nil];
  NSLog(@"js传来的json字典: %@", jsParameDic);
  for (NSString *key in jsParameDic.allKeys)
  {
      //将JS传来的JSON字典中key/value全部取出并打印
    NSLog(@"jsParameDic[%@]:%@", key, jsParameDic[key]);
  }
  [self beginOpenPhoto];
}
- (void)beginOpenPhoto
{
  // 主队列 异步打开相机
  dispatch_async(dispatch_get_main_queue(), ^{
    [self takePhoto];
  });
}

e:OC点击照片的代理中将图片传给HTML页面展示

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
  NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
  // 1、判断当前选择的类型是照片
  if ([type isEqualToString:@"public.image"])
  {
    // 2、获取照片并打印照片的大小
    getImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    NSLog(@"===Decoded image size: %@", NSStringFromCGSize(getImage.size));
    // 3、obtainImage 压缩图片 返回原尺寸
    indextNumb = indextNumb == 1?2:1;
    NSString *nameStr = [NSString stringWithFormat:@"Varify%d.jpg",indextNumb];
      
      
      //4、存储选中的图片并将图片展示到H5中
    [SaveImage_Util saveImage:getImage ImageName:nameStr back:^(NSString *imagePath) {
      dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"图片路径:%@",imagePath);
        /**5、传值数据到JS中,并展示数据
         *  这里是IOS 调 js 其中 setImageWithPath 就是js中的方法 setImageWithPath(),参数是字典
         *  jsContext[@"setImageWithPath"]为调用js中的方法
         *  //callWithArguments可以将参数传进去调用方法
         */
        JSValue *jsValue = self.jsContext[@"setImageWithPath"];
          
        [jsValue callWithArguments:@[@{@"imagePath":imagePath,@"iosContent":@"获取图片成功,把系统获取的图片路径传给js 让html显示"}]];
      });
    }];
    [picker dismissViewControllerAnimated:YES completion:nil];
  }
}

资料来源:https://www.jianshu.com/p/b03a46b47b14
Demo地址:https://github.com/Toxic-YX/JSOCInteraction

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,089评论 4 62
  • 今天,又是一年一度的国家公务员考试的开考日。虽然这两年的考录比是30多比1,还是比我当年考的时候的机率大多啦...
    知止堂阅读 588评论 1 8
  • 沉沦在那一世回忆 明知不必 也毫无意义 只是谁又勾起 相思却难以忘记 总劝别人珍惜 到自己就剩可惜 回想着过去的点...
    星尘梦羽阅读 168评论 0 4
  • 蔡旭盈每次都很晚回我,我打起精神给她上完了课。 王润婷因为舍友在她离开的时候决定另一舍友生日聚会的事情生气了,找我...
    以梦为马的牙云云阅读 101评论 0 0