> 基于UIWebview的混合编程是指同时使用原生的控件和UIWebView来展现应用界面。合理地使用该方案可以保证应用既有原生界面的流畅交互效果,又有Web界面的良好的动态修改和多平台复用的优势。 ———以上摘抄自《iOS开发进阶》 这一章是非常实用的一章,本文将提炼其中精华部分。 -------- #15.1 混合编程简介 基于UIWebview的混合编程本来就是一个挺普通常见的技术框架,但是自从国外开始用Hybird来称呼它时,这个技术突然间就变得“高大上”起来。 ### 什么时候使用Hybird - 排版复杂 - 界面的变化需求频繁 - 界面对用户的交互需求不复杂 # 15.2 使用模板引擎渲染HTML界面 有过网站开发经验的朋友都知道我们一般需要一个模板引擎来对界面进行渲染,如Django: ``` {{name}} ``` Django的模板引擎将替换 {{}}中的变量为字符创而对界面进行显示,在iOS中也有类似的模板引擎,我们在这里介绍一下GRMustache,GRMustache在github有很完整的使用教程,这里简单的提一下: ### 安装 - CocoaPod - Static Librar - Compile the raw sources 这部分相当简单,这部分大家可以自己去[github](https://github.com/groue/GRMustache)查阅。 ## 使用 ` #import “GRMustache.h" ` 假设我们的html文件是这样的,template.html: ``` {{name}} ``` 基本上所有的逻辑就是: - 从html获取到内容 - 通过模板引擎进行字符串替换 - 讲渲染后的字符串在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文件内容 NSString *content = [GRMustacheTemplate renderObject:data fromString:template error:nil]; //进行渲染 return content; } ``` 获取到渲染后的模板我们需要在webview上进行显示: ``` 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互调 ## OC通知JS UIWebview有一个方法 ` -(nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; ` 假设我们的JS方法是这样的: ``` function funcName(userid){ ……. } ``` 那么我们使用OC调用这个方法就是这样的: ``` [_webView stringByEvaluatingJavaScriptFromString:@“funcName(123456)"]; ``` ## JS通知OC JS通知OC并没有直接的方法,但是我们可以通过更新url的方式在UIWebview的delegate中拿到消息。 我们在js中调用方法 ``` //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); // 发起请求后这个iFrame就没用了,所以把它从dom上移除掉 iFrame.parentNode.removeChild(iFrame); iFrame = null; } ``` 我们可以看到我们设置一个“src”的属性,而这个属性就是我们在UIWebview的delegate中拿到字符串,如果传递一些简单的参数,也可以添加到这个字符串中。 我们在我们的OC代码中: ``` // _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) { ////////////// 你要执行的操作 //////////// } return YES; } ``` # 15.7 使用Safari进行调试 我们有时候可能会通过输出的方式来进行调试,在js中会使用console.log();方法,但是你会发现调用这个方法并不会在xcode的控制台输出(废话)。这个时候我们就可以通过safari来辅助我们进行开发。 - 我们需要打开safari的调试模式:safari->偏好设置->高级->勾选在菜单中显示“开发”菜单 ![勾选开发菜单](http://sbookreview.com/static/upload/images/banner/sjdhjsdhfjsdfhjsd.png) - 我们开需要在模拟器 或者真机上打开调试功能:设置->Safari->高级->Web检查器,打开开关: ![打开模拟器中的检查器](http://sbookreview.com/static/upload/images/banner/DF9D1BEC-A894-41E3-9F1F-324DCC168C50.png) 当你完成以上部分之后,当我们再运行项目,重新打开Safari(记得一定要重新启动Safari),在开发菜单中我们可以打开web检查器: ![打开Web检查器](http://sbookreview.com/static/upload/images/banner/168D06E5-0A0C-4DC4-BF9E-3FE637A7D138.png) 我们可以在web检查器中直接对html、css、js代码进行修改,同时在控制台会有对js等代码的调试、输出。(这个类似web开发时Chrome的检查功能) ![Web检查器](http://sbookreview.com/static/upload/images/banner/14F4BBFA-40F4-48D9-A3B0-68410E568499.png)