iOS - OC和网页JS的交互
来源:互联网 发布:工艺流程软件软件 编辑:程序博客网 时间:2024/04/28 12:56
我们知道,在iOS开发过程中,有时候会用webview加载一张网页,网页上有一些按钮或者其他的一些链接,要使这些按钮有实际的作用,1⃣️要么就是网页部分在HTML文件内部自己实现方法,2⃣️要么就是通过OC和网页的交互,在本app内OC实现点击网页的按钮,可以触发自己OC写的方法。
下面我讲两种常用的方法。
第一种是遵守webview的协议,通过实现协议方法截取网络请求,通过这个截取到的网络请求进行解析,然后实现自己的方法。
第二种方法是用了一个叫WebViewJavascriptBridge 的第三方库进行桥接,这个方法就比较强大了,它既可以在oc部分写实现代码,也可以在网页JS部分写实现代码。
先放上我整理后的demo下载链接:
本人github上的JSandOC交互的demo
并且附上我参考的这个库下载地址为:(里面有demo,可以学着看看)
github上的下载地址
好了现在先上图,说明一下,现在的网页上的按钮和我本app内部,需要做哪些交互。
此页面为webview加载的图片,要做的便是分别点击这5个按钮(Facebook分享、QQ分享、微信分享、短信分享、邮件分享)在app内部得到响应。分享集成部分再次就不多说了,谢谢。
方法一:webview协议截取网络请求
- app部分(OC部分)
1.设置webview 加载网页
2.实现协议方法
3.实现网络截取后相应的方法
- (void)viewDidLoad { [super viewDidLoad]; UIWebView * webview = [[UIWebView alloc]initWithFrame:self.view.bounds]; webview.delegate = self; //http://127.0.0.1/WEB/initHtml.html 是我放在自己服务器的网页文件 [webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/WEB/initHtml.html"]]]; [self.view addSubview:webview];}#pragma mark ---webview协议方法#pragma mark ---拦截web网络请求-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ //获取自己的网络请求的网址字符串 NSString *url = request.URL.absoluteString; //自己定义的协议前缀 网页部分一会儿也是要设置成这个协议! NSString *scheme = @"xmg://"; //打印出自己获取的网络请求的网址是什么 NSLog(@"~~~~~ %@",url); //解析网址前缀是否为@"xmg://" if ([url hasPrefix:scheme]) { //截出方法名 NSString *actionName = [url substringFromIndex:scheme.length];、 //动态方法选择器 比如我获取的网址是xmg://mailShare 则会执行mailShare这个方法 [self performSelector:NSSelectorFromString(actionName) withObject:nil]; //不加载这个网络请求的页面 return NO; } //YES:加载这个网络请求的页面 return YES;}-(void)mailShare{ NSLog(@"1shareMail");}-(void)facebookShare{ NSLog(@"facebookShare");}
- 网页部分
在图片连接处 修改:
如图,只需要在连接的地方,将href的改成自己设定的协议+方法名即可!
这个方法比较简单!
方法二:利用WebViewJavascriptBridge第三方库进行JS和OC的桥接
1.app部分(OC部分)
①在新开的工程引用静态库
CoreGraphics.framework
Foundation.framework
UIKit.framework
WebKit.framework
②导入WebViewJavascriptBridge第三方库
③在使用的页面加入头文件WebViewJavascriptBridge.h 这个文件内包含了其他文件,所以只用导入这一个
④开始写代码
#import "ViewController.h"#import "WebViewJavascriptBridge.h"@interface ViewController ()<UIWebViewDelegate>//声明`WebViewJavascriptBridge`对象为属性@property (nonatomic,strong) WebViewJavascriptBridge * bridge;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];}-(void)viewWillAppear:(BOOL)animated{ if (_bridge) { return; } //用UIWebView加载web网页 UIWebView * webview = [[UIWebView alloc]initWithFrame:self.view.bounds]; webview.delegate = self; [self.view addSubview:webview]; //设置能够进行桥接 [WebViewJavascriptBridge enableLogging]; _bridge = [WebViewJavascriptBridge bridgeForWebView:webview]; [_bridge registerHandler:@"facebookObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@" ======FacebookObjcCallback ========= %@", data); //传话给网页说已经接收到 responseCallback(@"facebookObjcCallback回复网页,已经收到消息"); // }]; [_bridge registerHandler:@"QQShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@" ======QQShareObjcCallback ========= %@", data); //传话给网页说已经接收到 responseCallback(@"QQShareObjcCallback回复网页,已经收到消息"); }]; [_bridge registerHandler:@"WXShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@" ======WXShareObjcCallback ========= %@", data); //传话给网页说已经接收到 responseCallback(@"WXShareObjcCallback回复网页,已经收到消息"); // }]; [_bridge registerHandler:@"MessageShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@" ======MessageShareObjcCallback ========= %@", data); //传话给网页说已经接收到 responseCallback(@"MessageShareObjcCallback回复网页,已经收到消息"); // }]; [_bridge registerHandler:@"MailShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@" ======MailShareObjcCallback ========= %@", data); //传话给网页说已经接收到 responseCallback(@"MailShareObjcCallback回复网页,已经收到消息"); // }]; // oc传话给JS(网页执行) 网页部分会执行以下代码: /* bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) { log('ObjC called testJavascriptHandler with', data) var responseData = { 'Javascript Says':'Right back atcha!' } log('JS responding with', responseData) responseCallback(responseData) }) 接收 */ //网页接收OC的方法句柄名叫testJavascriptHandler 此时OC给JS传的数据是@{ @"foo":@"before ready" } [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; // 自定义按钮 此处没用,需要的可以自己打开使用 // [self renderButtons:webView]; //当你没有把网页放入服务器的话,可以把网页放在本地工程,这个时候就要执行以下的方法,用NSBoundle加载本地文件 // [self loadExamplePage:webview];} //自定义按钮 - (void)renderButtons:(UIWebView*)webView { UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [callbackButton setTitle:@"呼叫JS的Handle" forState:UIControlStateNormal]; [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; [self.view insertSubview:callbackButton aboveSubview:webView]; callbackButton.frame = CGRectMake(10, 400, 100, 35); callbackButton.titleLabel.font = font;} //可以通过自定义按钮实现方法,动态和JS进行交互 //注:本代码中没有写按钮去实现此方法,需要的同学可以自己去定义按钮实现此方法 - (void)callHandler:(id)sender { id data = @{ @"OC第一次发信息给JS": @"Hi there, JS,I am OC !" }; // testJavascriptHandler是JS部分接收OC传送消息的方法句柄 // data 是OC给JS传的数据 // response是JS接收到消息后给OC传的数据 [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { NSLog(@"JS收到消息后,回复给OC的消息为: %@", response); }];}//加载本地网页//本代码中的网页是从服务器获取,不是放在本地,放在本地的同学,可以用以下的方法加载- (void)loadExamplePage:(UIWebView*)webView { NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"codetest" ofType:@"html"]; NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; [webView loadHTMLString:appHtml baseURL:baseURL];}
2.网页部分(JS部分)
①在script标签内写桥接方法
②在a标签内记得表面id唯一标示,以便script能够获取此标签元素
<script> window.onerror = function(err) { log('window.onerror: ' + err) } function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } setupWebViewJavascriptBridge(function(bridge) { // JS注册接收消息的部分 名字叫testJavascriptHandler // function是接收消息后做的处理 bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) { var responseData = { 'Javascript Says':'Right back atcha!'}; //给OC的消息回执 responseCallback(responseData); }); document.body.appendChild(document.createElement('br')); //facebook连接出发方法 var facebookButton = document.getElementById('Facebook'); facebookButton.onclick = function(e) { e.preventDefault(); <!-- log('JS calling handler "FacebookObjcCallback"')--> //桥接呼叫OC句柄:facebookObjcCallback //并传送数据{'foo': 'bar'}过去 bridge.callHandler('facebookObjcCallback', {'foo': 'bar'}, function(response) { //JS接收到OC的消息回执 <!--log('JS got response', response)--> }); }; var QQShareBtn = document.getElementById('QQShare') QQShareBtn.onclick = function(a){ a.preventDefault(); bridge.callHandler('QQShareObjcCallback',{'QQ':'share'},function(response){ }); }; var wxShareBtn = document.getElementById('WXShare') wxShareBtn.onclick = function(a){ a.preventDefault(); bridge.callHandler('WXShareObjcCallback',{'WX':'share'},function(response){ }); }; var messageShareBtn = document.getElementById('MessageShare') messageShareBtn.onclick = function(a){ a.preventDefault(); bridge.callHandler('MessageShareObjcCallback',{'Message':'share'},function(response){ }); }; var mailShareBtn = document.getElementById('MailShare') mailShareBtn.onclick = function(a){ a.preventDefault(); bridge.callHandler('MailShareObjcCallback',{'Mail':'share'},function(response){ }); }; }); </script> <div class="share_box row-eq-height"> <div class="share_box_bg"> <div class="col-xs-3 share_btn share_btn_left" style=""> 來分享給好友! </div> <div class="col-xs-9 share_btn"> <div id='log'> <a href="" id='Facebook'> <img src="http://152.101.133.203:82/O2OBeauty/assets/images/invite_friend/invitefd_02-02.png"></a> <a href="" id='QQShare'> <img src="http://152.101.133.203:82/O2OBeauty/assets/images/invite_friend/invitefd_02-03.png"></a> <a href="" id="WXShare"> <img src="http://152.101.133.203:82/O2OBeauty/assets/images/invite_friend/invitefd_02-04.png"></a> <a href="" id="MessageShare"> <img src="http://152.101.133.203:82/O2OBeauty/assets/images/invite_friend/invitefd_02-05.png"></a> <a href="" id="MailShare"> <img src="http://152.101.133.203:82/O2OBeauty/assets/images/invite_friend/invitefd_02-06.png"></a> </div> </div> </div> </div>
总结:
1⃣️利用桥接的话,就可以进行双方的通信,JS部分可以做回执处理,OC部分也可以做回执处理。
注意点就是JS的Handle要命名好,OC部分的Handle也要命名好,不要搞混淆。
2⃣️而利用webview的协议方法的话,好处是只要双方规定了某一个协议,比如xmg://或其他,
单方面在OC处的webview协议方法解决,解析截取到的网络请求,这种方法实现起来比较快捷,
坏处就是,JS得不到回执啦(但好像也不是什么坏处)~
大家根据自己的需求选择自己适合的方法吧,谢谢大家能够看完!
- iOS - OC和网页JS的交互
- iOS ---oc和js交互
- iOS--js和oc交互
- UIWebView和网页的交互(JS中调用OC代码)
- UIWebView和网页的交互(OC中调执行JS)
- OC 和JS的交互
- IOS中的OC和JS的交互(一)
- iOS ---oc和js交互2
- iOS js和OC方法交互
- ios中oc的js的交互
- iOS OC与js的交互
- ios oc与js的交互总结
- OC和JS交互
- JS和OC交互
- oc 和 h5中js 的交互
- JS和OC交互的参考
- JS和OC进行交互的总结
- WKWebView的OC和JS交互
- FZU 2125 简单的等式
- ios基础知识整理1
- cntk
- jboss4.2.3漏洞修复
- 字体,截图,获取图库照片
- iOS - OC和网页JS的交互
- nagios插件,通过nrpe远程调用和本地执行结果不一致
- 上传文件到github
- MySQL快速学习入门
- ViewPager加fragment如何保存fragment里面的状态
- d3.js——update、enter、exit
- SQLZOO(SELECT within SELECT Tutorial)Writeup
- I00001 杨辉三角
- APP上架审核被拒(新增2016.04)