基于UIWebview的混合編程是指同時(shí)使用原生的控件和UIWebView來(lái)展現(xiàn)應(yīng)用界面顷啼。合理地使用該方案可以保證應(yīng)用既有原生界面的流暢交互效果彼乌,又有Web界面的良好的動(dòng)態(tài)修改和多平臺(tái)復(fù)用的優(yōu)勢(shì)蔑匣。
———以上摘抄自《iOS開(kāi)發(fā)進(jìn)階》
這一章是非常實(shí)用的一章秉氧,本文將提煉其中精華部分黑竞。
15.1 混合編程簡(jiǎn)介
基于UIWebview的混合編程本來(lái)就是一個(gè)挺普通常見(jiàn)的技術(shù)框架,但是自從國(guó)外開(kāi)始用Hybird來(lái)稱呼它時(shí)庙楚,這個(gè)技術(shù)突然間就變得“高大上”起來(lái)。
什么時(shí)候使用Hybird
- 排版復(fù)雜
- 界面的變化需求頻繁
- 界面對(duì)用戶的交互需求不復(fù)雜
15.2 使用模板引擎渲染HTML界面
有過(guò)網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn)的朋友都知道我們一般需要一個(gè)模板引擎來(lái)對(duì)界面進(jìn)行渲染趴樱,如Django:
<html>
<body>
<h1>{{name}}</h1>
</body>
</html>
Django的模板引擎將替換 {{}} 中的變量為字符創(chuàng)而對(duì)界面進(jìn)行顯示馒闷,在iOS中也有類似的模板引擎,我們?cè)谶@里介紹一下GRMustache伊佃,GRMustache在github有很完整的使用教程窜司,這里簡(jiǎn)單的提一下:
安裝
- [CocoaPod]
這部分相當(dāng)簡(jiǎn)單,這部分大家可以自己去github查閱航揉。
使用
#import “GRMustache.h"
假設(shè)我們的html文件是這樣的塞祈,template.html:
<html>
<body>
<h1>{{name}}</h1>
</body>
</html>
基本上所有的邏輯就是:
- 從html獲取到內(nèi)容
- 通過(guò)模板引擎進(jìn)行字符串替換
- 講渲染后的字符串在webview上顯示
-(NSString *)getTemplateFromName:(NSString *)name data:(NSDictionary *)data{
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:name]; //獲取到.html文件地址
NSString *template = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; //獲取.html文件內(nèi)容
NSString *content = [GRMustacheTemplate renderObject:data fromString:template error:nil]; //進(jìn)行渲染
return content;
}
獲取到渲染后的模板我們需要在webview上進(jìn)行顯示:
NSString *content = [self getTemplateFromName:@"template.html" data:@{@"name":@"StrongX"}];
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[self.webview loadHTMLString:content baseURL:baseURL];
OC與JS互調(diào)
OC通知JS
UIWebview有一個(gè)方法
-(nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
假設(shè)我們的JS方法是這樣的:
function funcName(userid){
…….
}
那么我們使用OC調(diào)用這個(gè)方法就是這樣的:
[_webView stringByEvaluatingJavaScriptFromString:@“funcName(123456)"];
JS通知OC
JS通知OC并沒(méi)有直接的方法,但是我們可以通過(guò)更新url的方式在UIWebview的delegate中拿到消息帅涂。
我們?cè)趈s中調(diào)用方法
//js通知OC
function js_call_oc(){
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", "ios://StrongX");
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
// 發(fā)起請(qǐng)求后這個(gè)iFrame就沒(méi)用了议薪,所以把它從dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
我們可以看到我們?cè)O(shè)置一個(gè)“src”的屬性尤蛮,而這個(gè)屬性就是我們?cè)赨IWebview的delegate中拿到字符串,如果傳遞一些簡(jiǎn)單的參數(shù)斯议,也可以添加到這個(gè)字符串中产捞。
我們?cè)谖覀兊腛C代碼中:
//
_webview.delegate = self;
//
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *urlstr = request.URL.absoluteString;
NSRange range = [urlstr rangeOfString:@"ios://StrongX"];
if (range.length!=0) { //////////////
你要執(zhí)行的操作
////////////
}
return YES;
}
15.7 使用Safari進(jìn)行調(diào)試
我們有時(shí)候可能會(huì)通過(guò)輸出的方式來(lái)進(jìn)行調(diào)試,在js中會(huì)使用console.log();方法哼御,但是你會(huì)發(fā)現(xiàn)調(diào)用這個(gè)方法并不會(huì)在xcode的控制臺(tái)輸出(廢話)坯临。這個(gè)時(shí)候我們就可以通過(guò)safari來(lái)輔助我們進(jìn)行開(kāi)發(fā)。
- 我們需要打開(kāi)safari的調(diào)試模式:safari->偏好設(shè)置->高級(jí)->勾選在菜單中顯示“開(kāi)發(fā)”菜單
-
我們開(kāi)需要在模擬器 或者真機(jī)上打開(kāi)調(diào)試功能:設(shè)置->Safari->高級(jí)->Web檢查器恋昼,打開(kāi)開(kāi)關(guān):
打開(kāi)模擬器中的檢查器
當(dāng)你完成以上部分之后看靠,當(dāng)我們?cè)龠\(yùn)行項(xiàng)目,重新打開(kāi)Safari(記得一定要重新啟動(dòng)Safari)液肌,在開(kāi)發(fā)菜單中我們可以打開(kāi)web檢查器:
我們可以在web檢查器中直接對(duì)html挟炬、css、js代碼進(jìn)行修改嗦哆,同時(shí)在控制臺(tái)會(huì)有對(duì)js等代碼的調(diào)試谤祖、輸出。(這個(gè)類似web開(kāi)發(fā)時(shí)Chrome的檢查功能)
歡迎加入iOS交流群537774852
更多文章