如今移动端的业务大多与web 相互的交集,为了更好更快的配合线上的业务,web 混合 开发 是移动人员具有的基础能力 在这,我总结下 我从几家公司中本身所学习的web 和 oc 交互的知识:html
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的使用方式 那么 如今我就继续往下面走 代理方法什么的 我就不写了 毕竟相对来讲都比较基础微信
####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的获取同样 用字符串接受 而后本身作处理就行了
写到这个就是很牛逼了,由于 以上代码 太复杂 ,用这个 贼简单 讲讲使用:
`
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 回调封装的,若是个人总结 能给你帮助,帮忙点个喜欢 谢谢
武汉的天气太热 .... 我要去冲澡
本次发布是摘自我的的简书,现转移到掘金