JS 与 OC 中的交互

JS 与 OC 中的交互

如今移动端的业务大多与web 相互的交集,为了更好更快的配合线上的业务,web 混合 开发 是移动人员具有的基础能力 在这,我总结下 我从几家公司中本身所学习的web 和 oc 交互的知识:html

UIWebVwe

UIWebView继承与UIView,所以,其初始化方法和通常的View同样,经过alloc和init进行初始化。 UIWebView 是用来加载加载网页数据的一个框。UIWebView能够用来加载pdf、word、doc 等等文件java

本地加载一个html 文件ios

- (void)viewDidLoad {
    [super viewDidLoad];
   
    //加载本地文件
    ///UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0))   iOS 12以后UIwebView 即将被废弃
    UIWebView * web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    
    NSURL * url =  [[NSBundle mainBundle] URLForResource:@"baidu.html" withExtension:nil];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    [web loadRequest:request];
    
    [self.view addSubview:web]; 
}
#pragma mark delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    return  YES;
}



-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

}

复制代码

直接根据连接加载网页web

[web loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"www.baidu.com" relativeToURL:nil]]];

复制代码

或者说 你根绝html 内容 直接加载 (项目中 本身作一个图片加载连接地址 而后加载内容... ) 具体参照HTML标签去处理数组

[self.webView loadHTMLString:@"<p>你所要表述的内容实质</p>" baseURL:nil];
复制代码

再就是加载文件,好比 PDF Word文件等等 这些都是web 能作到的 例如bash

#pragma 以二进制数据的形式加载文件 
- (void)loadDataFile  {  
    // 最最多见的一种状况  
    // 打开IE,访问网站,提示你安装Flash插件  
    // 若是没有这个应用程序,是没法用UIWebView打开对应的文件的  
       
    // 应用场景:加载从服务器上下载的文件,例如pdf,或者word,图片等等文件  
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"iOS 7 Programming Cookbook.pdf" withExtension:nil];  
       
    NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];  
    // 服务器的响应对象,服务器接收到请求返回给客户端的  
    NSURLResponse *respnose = nil;  
       
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&respnose error:NULL];  
       
    NSLog(@"%@", respnose.MIMEType);  
       
    // 在iOS开发中,若是不是特殊要求,全部的文本编码都是用UTF8  
    // 先用UTF8解释接收到的二进制数据流  
    [self.webView loadData:data MIMEType:respnose.MIMEType textEncodingName:@"UTF8" baseURL:nil];  
}

// 本地方法:
//从本地加载
    NSString *thePath = [[NSBundle mainBundle] pathForResource:@"User_Guide" ofType:@"pdf"];
    
    if (thePath) {
        NSData *pdfData = [NSData dataWithContentsOfFile:thePath];
        [self.webView loadData:pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
    }
复制代码

这个业务 楼主遇到过 作出的方式就是仿照微信去打开文件 而后去连接蓝牙设备 打印等等...服务器

以上说述 都是webview的使用方式 那么 如今我就继续往下面走 代理方法什么的 我就不写了 毕竟相对来讲都比较基础微信

UIWebview 交互JS

####1如何处理 代码拦截app

在iOS的工程代码中 web 和 js 的交互 主要的进行方式是在ide

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

这个代码中
NSLog(@"%@",request); 对request 对象进行打印 会发现这个reque 展现的是一个 路由 <NSMutableURLRequest: 0x600001354220> { URL: file:///Users/chenjiazhen/Library/Developer/CoreSimulator/Devices/D3F41005-1A57-4DAF-B3CE-47A986C9B867/data/Containers/Bundle/Application/BAF7F1D0-DCE6-4388-B810-6929B34058FA/demo.app/baidu.html } 这个就是web的文件地址所在的地方

在此 就能作一个处理 就是 NSLog(@"schme ===== %@",request.URL.scheme); 在此,能够处理web 中 js 交互不存在的交互方法 作拦截 固然,从这个地方也能够制定本身的一套方案 想怎么玩就怎么玩 js 全部的响应 都会根据你的想法去执行。

####2 js 与 oc 的交互

NSLog(@"%@",request.URL.pathComponents);
复制代码

此处是对js文件里面的路径的信息处理 好比 在此处 咱们传递一个字段 里面增长一个getsum的参数。 那么 在打印的地方就会出现

"/", getsum(1,3), Users, chenjiazhen, Library, Developer, CoreSimulator, Devices, "D3F41005-1A57-4DAF-B3CE-47A986C9B867", data, Containers, Bundle, Application, "B6FF5281-6954-45AB-935B-11626882C61B", "demo.app", "baidu.html" 相似于这样的一个信息数组,那么 就在getsum(1,3) 相似于这种调用方式 就会添加到这个信息数组中

就能拿到当前js 和 web 的交互数据了 而后 通过约定处理好后 oc 获取方法名 和 传递参数 使用 如下的代码 就能完成 js 调用 oc 的系统内容了

` [self performSelector:NSSelectorFromString(@"xxx") withObject:@"数据内容" afterDelay:0];

`

####3 oc 调用 js emmmmmm... 这个我以为没得必要详细的去总结 由于 以前已经在博客内容里面其实已经写到了 self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; 这个 就是 获取js 的系统方法的title名,固然 这里用的是最老套的方法 ,主要函数仍是 stringByEvaluatingJavaScriptFromString 固然 能够根据内容继续拓展 好比你想经过 oc 调用 js的函数
以alert为例子 [webView stringByEvaluatingJavaScriptFromString:@"showAlert("你要来和我一块儿玩吗 ?")"]; 这里 调用的就是js 的showAlert的方法 传递的信息技术括号内的内容

固然 如若 js 有数据信息返回 咱们就如title的获取同样 用字符串接受 而后本身作处理就行了

JavaScriptCore

写到这个就是很牛逼了,由于 以上代码 太复杂 ,用这个 贼简单 讲讲使用:

`

JSContext * CONT  = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

//建立一个全局的函数  也包括  调用js的方法参数
[CONT evaluateScript:@"var arr = ['haha','yes','baby']"];

//保存一段代码块
//当js 调用 方法的时候  这边就会处理 包括参数啊什么的
CONT[@"saveMyinfo"] = ^{
    //获取参数
    NSArray * ager = [JSContext currentArguments];
    
};
复制代码

`

这里 缩减了不少的方法处理判断,而后 咱们就是经过js 调用方法 在oc 中保存了一段代码块 ,js 调用 saveMyinfo 的时候,那么 这个信息就反馈在了oc 的代码中 咱们能够获取到系统参数啊什么的,比以上 简介不少,目前 我所看到的不少关于 js调用oc 的桥接封装 都是这么处理的 。固然 调用js 就是如上 evaluateScript这个方法,我就不过多的描述了。

以上 都是UIWebView 那么继续...

#WKWebView 不过多的介绍 iOS 都应该知道 这是Apple 对UIweb的优化 WKWebView:网页的渲染与展现

注意: #import <WebKit/WebKit.h>
     //初始化
       _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) configuration:config];
        // UI代理
        _webView.UIDelegate = self;
        // 导航代理
        _webView.navigationDelegate = self;
        // 是否容许手势左滑返回上一级, 相似导航控制的左滑返回
        _webView.allowsBackForwardNavigationGestures = YES;
        //可返回的页面列表, 存储已打开过的网页 
       WKBackForwardList * backForwardList = [_webView backForwardList];

        //        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.chinadaily.com.cn"]];
        //        [request addValue:[self readCurrentCookieWithDomain:@"http://www.chinadaily.com.cn"] forHTTPHeaderField:@"Cookie"];
        //        [_webView loadRequest:request];
        //页面后退
        [_webView goBack];
        //页面前进
         [_webView goForward];
        //刷新当前页面
        [_webView reload];
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"JStoOC.html" ofType:nil];
        NSString *htmlString = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
      //加载本地html文件
        [_webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
复制代码

WKWebViewConfiguration:为添加WKWebView配置信息

//建立网页配置对象
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        
        // 建立设置对象
        WKPreferences *preference = [[WKPreferences alloc]init];
        //最小字体大小 当将javaScriptEnabled属性设置为NO时,能够看到明显的效果
        preference.minimumFontSize = 0;
        //设置是否支持javaScript 默认是支持的
        preference.javaScriptEnabled = YES;
        // 在iOS上默认为NO,表示是否容许不通过用户交互由javaScript自动打开窗口
        preference.javaScriptCanOpenWindowsAutomatically = YES;
        config.preferences = preference;
        
        // 是使用h5的视频播放器在线播放, 仍是使用原生播放器全屏播放
        config.allowsInlineMediaPlayback = YES;
        //设置视频是否须要用户手动播放  设置为NO则会容许自动播放
        config.requiresUserActionForMediaPlayback = YES;
        //设置是否容许画中画技术 在特定设备上有效
        config.allowsPictureInPictureMediaPlayback = YES;
        //设置请求的User-Agent信息中应用程序名称 iOS9后可用
        config.applicationNameForUserAgent = @"ChinaDailyForiPad";
         //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
        WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
        //这个类主要用来作native与JavaScript的交互管理
        WKUserContentController * wkUController = [[WKUserContentController alloc] init];
        //注册一个name为jsToOcNoPrams的js方法
        [wkUController addScriptMessageHandler:weakScriptMessageDelegate  name:@"jsToOcNoPrams"];
        [wkUController addScriptMessageHandler:weakScriptMessageDelegate  name:@"jsToOcWithPrams"]; 
       config.userContentController = wkUController;
复制代码

WKUserContentController:这个类主要用来作native与JavaScript的交互管理

//这个类主要用来作native与JavaScript的交互管理
        WKUserContentController * wkUController = [[WKUserContentController alloc] init];
        //注册一个name为jsToOcNoPrams的js方法,设置处理接收JS方法的代理
        [wkUController addScriptMessageHandler:self  name:@"jsToOcNoPrams"];
        [wkUController addScriptMessageHandler:self  name:@"jsToOcWithPrams"];
        config.userContentController = wkUController;
       //用完记得移除
       //移除注册的js方法
        [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"jsToOcNoPrams"];
       [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"jsToOcWithPrams"];
复制代码

WKScriptMessageHandler:这个协议类专门用来处理监听JavaScript方法从而调用原生OC方法,和WKUserContentController搭配使用。

注意:遵照WKScriptMessageHandler协议,代理是由WKUserContentControl设置

   //经过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    //用message.body得到JS传出的参数体
    NSDictionary * parameter = message.body;
    //JS调用OC
    if([message.name isEqualToString:@"jsToOcNoPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:@"不带参数" preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
        
    }else if([message.name isEqualToString:@"jsToOcWithPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:parameter[@"params"] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
    }
}

复制代码

以上就是WKweb的一些介绍 和 详细的使用方式了 ... 写这么多 感受脑壳都要爆炸了 ,我在总结下

oc 调用 js 
 [_webView evaluateJavaScript:@"你所须要的传递的参数 或者你响应的方法 " completionHandler:^(id _Nullable data, NSError * _Nullable error) {
 //下面是返回的回调信息
        NSLog(@"我是回调信息");
    }];
    
 js  调用 oc 
   //经过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    //用message.body得到JS传出的参数体
    NSDictionary * parameter = message.body;
    //JS调用OC
    if([message.name isEqualToString:@"jsToOcNoPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:@"不带参数" preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
        
    }else if([message.name isEqualToString:@"jsToOcWithPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:parameter[@"params"] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
    }
}
复制代码

以上就是业务中经常使用到得js oc 交互的总结,目前网上 不少的第三方封装介绍对这些函数信息的封装处理后 直接block 回调封装的,若是个人总结 能给你帮助,帮忙点个喜欢 谢谢

武汉的天气太热 .... 我要去冲澡

本次发布是摘自我的的简书,现转移到掘金

相关文章
相关标签/搜索