OC&JS交互实例浅析

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


OC&JS交互实例浅析_第1张图片
JavaScriptCore简介图.png

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

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

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内部方法的注释



  
    
      
      
  
    

JS与iOS交互

JS页面获取iOS系统图片

OC&JS交互实例浅析_第2张图片
效果图.png

三、webView加载HTML方法的使用

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

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

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

@interface ViewController (){
  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 *)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

你可能感兴趣的:(OC&JS交互实例浅析)