前言:
現(xiàn)在大多數(shù)的iOS程序已經(jīng)并不是全部原生開發(fā)
了,因?yàn)樵_發(fā)的頁面不能滿足經(jīng)常性變動
的需求,所以我們會被要求嵌入h5頁面
养交,我們既能滿足h5頁面的實(shí)時更新,也能實(shí)現(xiàn)與h5直接的交互
.
話不多說宙枷,開搞钙畔。
采用”WebViewJavascriptBridge“
框架
tset.html
<!doctype html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<style type='text/css'>
html { font-family:Helvetica; color:#222; }
h1 { color:steelblue; font-size:24px; margin-top:24px; }
button { margin:0 3px 10px; font-size:12px; }
.logLine { border-bottom:1px solid #ccc; padding:4px 2px; font-family:courier; font-size:11px; }
</style>
</head>
<body>
<h1>WebViewJavascriptBridge Demo</h1>
<script>
window.onerror = function(err) {
log('window.onerror: ' + err)
}
/*這段代碼是固定的甚疟,必須要放到j(luò)s中*/
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)
}
var uniqueId = 1
function log(message, data) {
var log = document.getElementById('log')
var el = document.createElement('div')
el.className = 'logLine'
el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
if (log.children.length) {
log.insertBefore(el, log.children[0])
} else {
log.appendChild(el)
}
}
/*與OC交互的所有JS方法都要放在此處注冊仗岖,才能調(diào)用通過JS調(diào)用OC或者讓OC調(diào)用這里的JS*/
setupWebViewJavascriptBridge(function(bridge) {
/* Initialize your app here */
/*我們在這注冊一個js調(diào)用OC的方法,不帶參數(shù)古拴,且不用ObjC端反饋結(jié)果給JS:打開本demo對應(yīng)的博文*/
bridge.registerHandler('openWebviewBridgeArticle', function() {
log("openWebviewBridgeArticle was called with by ObjC")
})
/*JS給ObjC提供公開的API箩帚,在ObjC端可以手動調(diào)用JS的這個API。接收ObjC傳過來的參數(shù)黄痪,且可以回調(diào)ObjC*/
bridge.registerHandler('getUserInfos', function(data, responseCallback) {
log("Get user information from ObjC: ", data)
responseCallback({'userId': '123456', 'blog': '標(biāo)哥的技術(shù)博客'})
})
/*JS給ObjC提供公開的API紧帕,ObjC端通過注冊,就可以在JS端調(diào)用此API時桅打,得到回調(diào)是嗜。ObjC端可以在處理完成后,反饋給JS挺尾,這樣寫就是在載入頁面完成時就先調(diào)用*/
bridge.callHandler('getUserIdFromObjC', function(responseData) {
log("JS call ObjC's getUserIdFromObjC function, and js received response:", responseData)
})
document.getElementById('blogId').onclick = function (e) {
log('js call objc: getBlogNameFromObjC')
bridge.callHandler('getBlogNameFromObjC', {'blogURL': 'http://www.henishuo.com'}, function(response) {
log('JS got response', response)
})
}
})
</script>
<div id='buttons'></div> <div id='log'></div>
<div>
<input type="button" value="getBlogNameFromObjC" id="blogId"/>
</div>
</body>
</html>
ViewController
//
// ViewController.m
// WebViewBridgeDemo
//
// Created by huangyibiao on 16/3/9.
// Copyright ? 2016年 huangyibiao. All rights reserved.
//
#import "ViewController.h"
#import "WebViewJavascriptBridge.h"
#import <WebKit/WebKit.h>
@interface ViewController () <UIWebViewDelegate>
@property UIWebView *webView;
@property WebViewJavascriptBridge *bridge;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSString *appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[self.webView loadHTMLString:appHtml baseURL:baseURL];
// 開啟日志
[WebViewJavascriptBridge enableLogging];
// 給哪個webview建立JS與OjbC的溝通橋梁
self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[self.bridge setWebViewDelegate:self];
[self renderButtons:self.webView];
// JS主動調(diào)用OjbC的方法
// 這是JS會調(diào)用getUserIdFromObjC方法鹅搪,這是OC注冊給JS調(diào)用的
// JS需要回調(diào),當(dāng)然JS也可以傳參數(shù)過來遭铺。data就是JS所傳的參數(shù)丽柿,不一定需要傳
// OC端通過responseCallback回調(diào)JS端,JS就可以得到所需要的數(shù)據(jù)
[self.bridge registerHandler:@"getUserIdFromObjC" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"js call getUserIdFromObjC, data from js is %@", data);
if (responseCallback) {
// 反饋給JS
responseCallback(@{@"userId": @"123456"});
}
}];
[self.bridge registerHandler:@"getBlogNameFromObjC" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"js call getBlogNameFromObjC, data from js is %@", data);
if (responseCallback) {
// 反饋給JS
responseCallback(@{@"blogName": @"標(biāo)哥的技術(shù)博客"});
}
}];
[self.bridge callHandler:@"getUserInfos" data:@{@"name": @"標(biāo)哥"} responseCallback:^(id responseData) {
NSLog(@"from js: %@", responseData);
}];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSLog(@"webViewDidStartLoad");
}
- (void)renderButtons:(UIWebView*)webView {
UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[callbackButton setTitle:@"打開博文" forState:UIControlStateNormal];
[callbackButton addTarget:self action:@selector(onOpenBlogArticle:) forControlEvents:UIControlEventTouchUpInside];
[self.view insertSubview:callbackButton aboveSubview:webView];
callbackButton.frame = CGRectMake(10, 400, 100, 35);
callbackButton.titleLabel.font = font;
UIButton* reloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[reloadButton setTitle:@"刷新webview" forState:UIControlStateNormal];
[reloadButton addTarget:webView action:@selector(reload) forControlEvents:UIControlEventTouchUpInside];
[self.view insertSubview:reloadButton aboveSubview:webView];
reloadButton.frame = CGRectMake(110, 400, 100, 35);
reloadButton.titleLabel.font = font;
}
- (void)onOpenBlogArticle:(id)sender {
// 調(diào)用打開本demo的博文
[self.bridge callHandler:@"openWebviewBridgeArticle" data:nil];
[self.bridge callHandler:@"openTest" data:nil];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@"webViewDidFinishLoad");
//自定義添加js代碼魂挂,并且實(shí)現(xiàn)
[webView stringByEvaluatingJavaScriptFromString:@"log('我的自定義的','我是自定義的消息')"];
[webView stringByEvaluatingJavaScriptFromString:@"window.WebViewJavascriptBridge.registerHandler('openTest', function() {\
log('test add js')\
})"];
}
@end
步驟分析:
1.首先為ViewController分配一個bridge
2.在html中也分配一個bridge
3.雙方均注冊registerHandler 方法
4.雙方均可用手動 callHanlder 調(diào)用對方注冊的方法