OS開發(fā)趨勢:Native與H5+JS 解決方案
支付寶紅包火了吨枉,微信紅包火了,作為開發(fā)者梦裂,敏感的就發(fā)現(xiàn)之前并不被看好的H5已經(jīng)悄悄滲透進來告匠,在原生(Native)代碼中部分功能采用動態(tài)網(wǎng)頁(HTML5+JavaScript)來實現(xiàn),即保證了整體App的流暢度著隆,又能及時推出一些活動和動態(tài)扰楼,目前主流App已經(jīng)開始默認這種開發(fā)模式,未來的移動開發(fā)團隊也需要H5的小伙伴加入進來了旅东,實現(xiàn)動靜結(jié)合灭抑,讓頁面更加靈活多變,接下來筆者就根據(jù)之前涉及到的項目經(jīng)驗來談?wù)勗c網(wǎng)頁交互的那些不得不說的瑣事:
一抵代、 原生代碼中直接加載頁面
1.? ? 具體案例
加載本地/網(wǎng)絡(luò)HTML5作為功能介紹頁
2.? ? 代碼示例
//本地
-(void)loadLocalPage:(UIWebView*)webView
{
NSString* htmlPath = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"html"];
NSString* appHtml =[NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncodingerror:nil];
NSURL *baseURL = [NSURLfileURLWithPath:htmlPath];
[webView loadHTMLString:appHtmlbaseURL:baseURL];
}
//網(wǎng)絡(luò)
-(void)loadWebPage:(UIWebView *)webView
{
NSURL *url = [NSURLURLWithString:@"http://www.baidu.com"];
NSURLRequest *request = [NSURLRequestrequestWithURL:url];
[webView loadRequest:request];
}
3.? ? 額外操作
a? iOS中承載網(wǎng)頁的容器是UIWebView腾节,可以借助它的代理來監(jiān)聽網(wǎng)頁加載情況;
b? 在加載過程中荤牍,我們還可以獲取該網(wǎng)頁中的meta值案腺,例如代碼:
NSString *shareUrl = [messWebViewstringByEvaluatingJavaScriptFromString:@"document.getElementsByName(\"shareUrl\")[0].content"];
就是從meta中得到shareUrl對應(yīng)的value值;
c? 截獲當前是發(fā)起的那種請求康吵,以便native來做對應(yīng)的控制劈榨,例如代碼:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType
{
NSString *requestString = [[[request URL]absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([requestString hasPrefix:@"http://customersharetrigger"]){
//執(zhí)行一些操作
return NO;
}
return YES;
} //可以監(jiān)聽到這個請求,從而達到控制作用晦嵌;
二同辣、? 原生代碼操作頁面元素
1.? ? 具體案例
在嵌入H5后需要操作頁面元素
2.? ? 代碼示例
a、獲取當前頁面的url惭载。
-(void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
}
b旱函、獲取頁面title:
NSString *currentURL = [webViewstringByEvaluatingJavaScriptFromString:@"document.location.href"];
NSString *title = [webviewstringByEvaluatingJavaScriptFromString:@"document.title"];
c、修改界面元素的值描滔。
NSString *js_result = [webViewstringByEvaluatingJavaScriptFromString:@"document.getElementsByName('q')[0].value='朱祁林';"];
d棒妨、表單提交:
NSString *js_result2 =[webView stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit();"];
3.? ? 代碼說明
stringByEvaluatingJavaScriptFromString方法可以將javascript代碼片段嵌入到頁面中,通過這個方法就可以讓iOS與UIWebView中的網(wǎng)頁元素交互含长,例如上面的代碼片段券腔,它
功能非常的強大伏穆,用起來也相對簡單,通過它我們可以很方便的操作頁面元素纷纫,而且能直接插入一段JS方法枕扫,然后調(diào)用該方法執(zhí)行;
三涛酗、? 原生代碼處理本地H5+JS
1.? ? 具體案例
需要動態(tài)顯示曲線圖铡原,如果直接加載繪制圖形特別慢,所以采用本地放置模板商叹,傳入?yún)?shù),然后模板自動繪制只泼,提高體驗剖笙,加快繪制;
2.? ? 示例代碼
-(void)loadWebPage:(UIWebView *)webView
{
NSURL *localPathURL = [[NSBundlemainBundle] URLForResource:@"detail" withExtension:@"html"subdirectory:@"htmlResources"];
NSString *localPathUrl = [localPathURLabsoluteString];
NSString *localParamPathUrl = [NSStringstringWithFormat:@"%@?symbol=%@&t=%f",localPathUrl,self.stockCode,self.time];
NSURL *requestURL = [NSURLURLWithString:localParamPathUrl];
[webView loadRequest:[NSURLRequestrequestWithURL:requestURL]];
}
3.? ? 代碼說明
a 這里需要采用絕對路徑拖入H5模板请唱,就是選擇CreateFolder Reference, 只有這樣才能保證H5能調(diào)用到本地的JS代碼弥咪,不然加載不成功,這個最初找了很多原因十绑,最后才發(fā)現(xiàn)是拖入時候選擇問題;
b 如果要加入?yún)?shù)聚至,注意需要先轉(zhuǎn)成string,然后再轉(zhuǎn)為URL;
四本橙、? 原生代碼與網(wǎng)頁交互通信
1.? ? 具體案例
原生代碼與H5相互調(diào)用方法扳躬,并傳遞參數(shù),而且能回調(diào)數(shù)據(jù)甚亭;
2.? ? 借助第三方實現(xiàn)
WebViewJavascriptBridge贷币,該開源庫非常完美的解決了原生代碼與H5交互,即互毆亏狰;
3.? ? 代碼示例
1.初始化一個webview(viewdidload)
UIWebView* webView =[[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:webView];
2.將此webview與WebViewJavascriptBridge關(guān)聯(lián)(viewdidload)
if (_bridge) { return; }
[WebViewJavascriptBridge enableLogging];
_bridge = [WebViewJavascriptBridgebridgeForWebView:webView webViewDelegate:self handler:^(id data,WVJBResponseCallback responseCallback) {
NSLog(@"ObjC received message from JS:%@", data);
responseCallback(@"Response formessage from ObjC");
}];
此時webview就與js搭上橋了役纹。下面就是方法的互調(diào)和參數(shù)的互傳。
(1) js調(diào)oc方法(可以通過data給oc方法傳值暇唾,使用responseCallback將值再返回給js)
[_bridgeregisterHandler:@"testObjcCallback" handler:^(id data,WVJBResponseCallback responseCallback) {
NSLog(@"testObjcCallback called:%@", data);
responseCallback(@"Response fromtestObjcCallback");
}];
這里注意testObjcCallback這個方法的標示促脉。html那邊的命名要跟ios這邊相同,才能調(diào)到這個方法策州。當然這個名字可以兩邊商量著自定義瘸味。簡單明確即可。
(2)oc調(diào)js方法(通過data可以傳值抽活,通過 response可以接受js那邊的返回值 )
id data = @{@"greetingFromObjC": @"Hi there, JS!" };
[_bridgecallHandler:@"testJavascriptHandler" data:data responseCallback:^(idresponse) {
NSLog(@"testJavascriptHandlerresponded: %@", response);
}];
注意這里的 testJavascriptHandler也是個方法標示硫戈。
(3)oc給js傳值(通過 response接受返回值 )
[_bridge send:@"Astring sent from ObjC to JS" responseCallback:^(id response) {
NSLog(@"sendMessage got response:%@", response);
}];
(4)oc給js傳值(無返回值)
[_bridge send:@"A string sent from ObjC after Webview hasloaded."];
五、 總結(jié)
關(guān)于Native和H5的交互有各種形式下硕,隨著H5越來越成熟丁逝,未來的趨勢就是兩者形影不離汁胆,讓App更具靈活性和實效性,也一定程度上提高了開發(fā)效率和迭代周期霜幼,是企業(yè)級移動應(yīng)用開發(fā)的必選解決方案嫩码,推薦:IT面試寶典(典型)。