作者:Love@YR
鏈接:http://blog.csdn.net/jingqiu880905/article/details/51736367
請尊重原創,謝謝!
關於js和native的交互文章已經很多了,推薦看下:
http://blog.devtang.com/2012/03/24/talk-about-uiwebview-and-phonegap/
其中我們知道的如:
1. 如何發起一個request
以UIWebView爲例:
NSMutableURLRequest *mReq = [NSMutableURLRequest requestWithURL:theURLToLoad];
[self.webView loadRequest:mReq];
或者加載本地的:
NSString * path = [[NSBundle mainBundle] bundlePath];
NSURL * baseURL = [NSURL fileURLWithPath:path];
NSString * htmlFile = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString * htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:(NSUTF8StringEncoding) error:nil];
[self.webView loadHTMLString:htmlString baseURL:baseURL];
- 然後我們也知道在webview的delegate方法:
webView:shouldStartLoadWithRequest:navigationType:
那裏去截獲js。
一直不明白的是這個方法是如何截獲到js的。
直到看到上述文章
貼下代碼:
// Javascript 語言
// 通知 iPhone UIWebView 加載 url 對應的資源
// url 的格式爲: gap:something
function loadURL(url) {
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", url);
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");//可不要
iFrame.setAttribute("width", "0px");//可不要
iFrame.setAttribute("frameborder", "0");//可不要
document.body.appendChild(iFrame);
// 發起請求後這個 iFrame 就沒用了,所以把它從 dom 上移除掉
setTimeout(function(){
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
},200)
}//這裏最好是加到timeOut方法裏
}
然而js基礎薄弱不懂爲啥這幾句代碼就讓UIWebView 加載了 url 對應的資源
那麼現在我想知道js和native如何交換數據的。
下載https://github.com/tangqiaoboy/UIWebViewSample 的代碼,然後做如下改動:
index.html那邊:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<script language="javascript">
function loadURL(url) {
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", url);
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
// 發起請求後這個iFrame就沒用了,所以把它從dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
function check(){
var params = {
param:"abc",//h5傳給native的參數
callbackMethod:"nativeCallback"//native那邊事件處理完之後的h5回調方法
}
var urlstr = "jean://h5/plugin?jsparam="+JSON.stringify(params);
alert('urlstr is '+urlstr);
loadURL(urlstr);
}
//call back method
function nativeCallback(callbackParam){
alert('the param passed from native is: '+callbackParam);
callbackfun(function(){
alert('success~~~');
},function(){
alert('failed!!!');
});
}
function callbackfun(c1,c2){
var success=true;
alert('start to call the callback');
if(success) c1();
else c2();
}
</script>
</head>
<body>
<h1>這是一段內容</h1>
<input type="button" value="測試" onclick="check()" />
</body>
</html>
ViewController.m 裏
#define kURLJSParamTagKey @"jsparam"
webView:shouldStartLoadWithRequest:navigationType:那邊:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL * url = [request URL];
if ([[url scheme] isEqualToString:@"jean"]) {
NSString *urlStr=[url query];//拿到查詢字符串
NSString *paramString = [urlStr substringFromIndex:[kURLJSParamTagKey length] + 1];//拿到jsparam=後面的內容
paramString =[paramString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//URL解碼
NSDictionary *urlParamMap = [paramString objectFromJSONString];//string轉換成dictionary,需引入jsonkit
NSString *param = [urlParamMap objectForKey:@"param"];//拿到h5傳給native的數據
NSLog(@"the data passed from h5 to native is %@",param);
NSString *callbackMethod = [urlParamMap objectForKey:@"callbackMethod"];//拿到callbackMethod的名字
NSString *callbackParam=@"88888888";//你想回傳給h5的數據
NSString * js =[NSString stringWithFormat:@"%@('%@')",callbackMethod,callbackParam];//js字串
[self.webView stringByEvaluatingJavaScriptFromString:js];//執行js
// UIAlertView * alertView = [[[UIAlertView alloc] initWithTitle:@"test" message:[url absoluteString] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
// [alertView show];
return NO;
}
return YES;
}
即可。這裏還需要把JSONKit庫加進來。
在js 代碼那邊可以設置要傳給native的數據,設置native做完事情之後想讓js回調的方法。
在native代碼那邊可以設置傳給js的數據。
這樣就做到了交換數據的功能,且native這邊的開發人員不再需要知道回調方法是啥。