作者董一凡自述:作为一名写了十年代码的程序员,现在我最拿手的范畴是移动渠道的客户端开发,在移动范畴的开发时刻超越七年,前前后后涉猎过许多个渠道。跟着大部分移动渠道自己走向逝世,现在我也首要专心在了iOS和Android两大移动渠道,偶然也会客串下Windows这个不知道是移动仍是桌面的渠道。 十年前,我刚入行的时分,从前以为自己将会永久做一个C++程序员,所以花了许多时刻在C++上。现在C++也是我作业所用的主力言语之一,作业之外也会偶然写点什么文娱一下。 写了一些年程序后,总算认识到了之前定位的狭窄,所以开端广泛的学习各种技能,各式各样的言语也学了许多,值得幸亏的是,几年折腾下来,我一向也没有对写代码这件事感到厌恶,所以我又以为自己将会永久把开发做下去。 现在,我也觉得开发是一个可以终身做下去的作业,不过除了作业我还想寻求更多的东西,从这些年的阅历来看,其间贯穿一直的便是在不断的学习,想理解这一点后,我开端除技能之外更广范畴的学习,比方日语,画画,规划,钢琴等等,给自己的定位也变成了在往后作为一名终身学习者。
一 iOS hybrid App 简略介绍
咱们应该多少都知道,iOS 设备上有两种进口,一是经过 App Strore 下载一个个的 App,另一个是用体系浏览器去拜访网页。前者咱们一般称为原生运用,后者便是传统意义上的网页。两者各有特点,开发一个原生运用,一般是运用 Apple 给咱们供给的开发工具和 Cocoa 结构。优势便是可以运用到体系的一切特性,做出很帅的特性而不丢失任何的功用,而缺陷便是每次 App 供给新功用都必须从头打包 App,提交给 Apple 进行审阅,经过今后再上架 App Store,终究用户再晋级,均匀需求两周的时刻。相反,写一个网页则彻底没有这个约束,服务器做一次晋级,用户经过浏览器再拜访,便是最新的了,而写网页的缺陷则是遭到很大的约束,许多体系特性是无法拜访的,并且功用往往不高,以至于很难完成一些很帅的作用。
鉴于原生运用和网页各有优势,所以就衍生出了一种介于两者之间的开发办法–混合运用(hybrid App)。其特点是在原生运用中嵌入一个浏览器组件,然后经过某种办法,让原生代码和网页可以双向通讯,成果便是可以在需求原生功用的时分运用原生功用,而适宜放在网页端的部分就放在服务器上。某种程度上运用到了两者的优势。另一个优势便是,因为网页技能在 iOS 和 Android 上是相同的,所以网页的这部分也就天然可以跨渠道了。
二 怎样完成 hybrid App
完成一个 hybrid App 最简略的办法便是运用 Apache Cordova 开源结构。Cordova 现已帮你做好了一切的网页和原生运用之间的桥接作业,你需求做的便是依据他的文档去写对应的网页代码和原生代码就行了。具体请参阅官方网站
惋惜的是,咱们总有些场景无法运用 Cordava,比方我从前的一个项目,项目首要是要供给一个 SDK ,SDK 自身要运用 hybrid 的技能。可是 SDK 的用户或许也会用到 Cordova,有些状况下,两者用的 Cordova 为不同版别,正好无法兼容。所以就需求自己去完成 hybrid App 的底层了。
三 iOS hybrid App 的底层完成
1. 原生代码调用网页中的 JavaScript 函数
假定咱们的网页中有如下代码
[scripttype=text/javascript]functionmyFunc(){returnTextfromweb}[/script]
原生代码可以用如下办法调用 myFunc()
NSString*result=[self.webViewstringByEvaluatingJavaScriptFromString:@myFunc()];
在这儿 result 就等于 Text from web
2. 网页中的 JavaScript 调用体系的原生代码
这一步比上边的要杂乱一些,iOS 不像 Android 可以直接给网页中的 JavaScript 函数注入一个原生代码的接口。这儿咱们会用一个比较弯曲的办法来完成。
假定 Objective-C 的类里有一个办法
-(void)nativeFunction:(NSString*)args{}
JavaScript 里咱们用下边的办法来终究调用到上边这个办法
window.JSBridge.callFunction(callNativeFunction,somedata);
在咱们的页面里,是没有 JSBridge.callFunction 存在的,这一步咱们要在原生代码端注入。
在 webView 的 delegate 的 – (void)webViewDidFinishLoad:(UIWebView *)webView 里咱们用下边的办法注入 JavaScript
NSString*js=@(function(){\window.JSBridge={};\window.JSBridge.callFunction=function(functionName,args){\varurl=\bridge-js://invoke?\;\varcallInfo={};\callInfo.functionname=functionName;\if(args)\{\callInfo.args=args;\}\url+=JSON.stringify(callInfo);\varrootElm=document.documentElement;\variFrame=document.createElement(\IFRAME\);\iFrame.setAttribute(\src\,url);\rootElm.appendChild(iFrame);\iFrame.parentNode.removeChild(iFrame);\};\returntrue;\})();;[webViewstringByEvaluatingJavaScriptFromString:js];
简略解释一下,首要咱们在 window 里创立一个叫 JSBridge 的目标,然后在里面界说一个办法 callFunction,这个办法的作用是把两个参数打包为 JSON 字符串,然后顺便到咱们自界说的 URL bridge-js://invoke? 后边,终究用 IFRAME 的办法来加载这个 URL
这么做的原因是,当加载 IFRAME 的时分,就会调用 webView 的 delegate 的 – (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 办法,其间 request 便是咱们方才自界说的那个 URL,在这个办法里咱们做如下处理
NSURL*url=[requestURL];NSString*urlStr=url.absoluteString;return[selfprocessURL:urlStr];
processURL 函数如下
-(BOOL)processURL:(NSString*)url{NSString*urlStr=[NSStringstringWithString:url];NSString*protocolPrefix=@bridge-js://invoke?;if([[urlStrlowercaseString]hasPrefix:protocolPrefix]){urlStr=[urlStrsubstringFromIndex:protocolPrefix.length];urlStr=[urlStrstringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];NSError*jsonError;NSDictionary*callInfo=[NSJSONSerializationJSONObjectWithData:[urlStrdataUsingEncoding:NSUTF8StringEncoding]options:kNilOptionserror:jsonError];NSString*functionName=[callInfoobjectForKey:@functionname];NSString*args=[callInfoobjectForKey:@args];if([functionNameisEqualToString:@callNativeFunction]){[selfnativeFunction:args];}returnNO;}returnYES;}
从 bridge-js://invoke? 这个自界说的 URL 里面把顺便在后边 JSON 字符串解析出来,然后判别 functionname key 的值假如是 callNativeFunction 那么就去调用原生办法 nativeFunction, 假如需求完成更多的办法调用,只需增加这个映射联系就行了。
至此,JavaScript 和 Objective-C 代码的双向调用就都完成了。
四 功用监测
Hybrid 和原生运用之间的争辩一向以来都不少,其核心问题其实便是怎样平衡开发本钱和用户体会之间的联系。Hybrid的开发本钱一般来说要低于原生运用,然后其体会总是要差一些。为了让 Hybrid 的用户体会能更或许的挨近原生运用,功用监测就显的更为重要了。
影响 App 运用体会一般来讲有两个首要方面
榜首方面是 UI 的呼应速度,UI 的流通与否给用户的体会是十分不相同的。对这方面的功用监测,一般的做法便是在首要的交互函数里打上时刻戳,而关于体系的 View,也可以选用 Method Swizzle 的办法对一切的体系函数的调用时刻进行计算。
二是网络,而因为现在的大部分 App 都多少有了网络恳求,所以网络的恳求速度也会很大程度上影响用户体会。网络问题在 Hybrid App 就体现的更显着。Hybrid App 总是会去加载服务器端的页面,在页面加载出来之前,很或许整个手机屏幕是空白的,假如空白时刻太长,将是一个很糟糕的作业,所以实时的监测恳求网页的时刻,以及页面的加载速度就十分有必要了。针对 webView,主张在它的 delegate 的几个办法里打上时刻戳,以此来计算页面恳求和加载的时刻。
总归完成起来,并不是一个十分杂乱的作业。但是功用监测的作业,完成仅仅其间的一个方面,因为用户的运用习气,实践的网络环境各种问题,功用监测并不是在开发阶段监测一下就算完了的,一般来说,总是得把监测作业布置到终究用户的手机上去的,假如是一个用户量不小的 App,那么怎样把收集到的许多数据很好的计算显现出来,这彻底是另一回事了,把这事做好,要牵扯到许多的数据安排,前端展现的作业,实践的施行肯定不是个简略的作业。
所幸,现在现已有许多公司帮咱们完成了这个作业,比方 New Relic,App dynamics,Compuware,听云等。这次咱们就以听云为例,看看他们是怎样来做功用监测这件事的。
五 听云探针(iOS App版)的运用
听云对 App 的功用监测运用起来仍是比较简略的,简略过程如下
恳求完听云的账户后,在增加 App 的当地填写相关信息
之后就会得到一个仅有的 App Key
然后下载听云的 iOS SDK 的 Framework,拷贝到项目中,留意增加以下 4 个额定的体系库
-
CoreTelephony.framework
-
Security.framework
-
SystemConfiguration.framework
-
libz.dylib
然后在 App 的 pch 文件中包括听云 App 探针的头文件
#import
终究将 main.m 中参加
[NBSAppAgentstartWithAppID:App_Key];
代码一般为下边的姿态
intmain(intargc,char*argv[]){@autoreleasepool{[NBSAppAgentstartWithAppID:App_Key];returnUIApplicationMain(argc,argv,nil,NSStringFromClass([AppDelegateclass]));}}
这样整个集成作业就完成了。发动 App,假如在 Log 日志中有如下内容显现就表明代码集成成功
NBSAppAgent2.2.2.1---->start!SuccesstoconnecttoNBSSERVER
六 听云监测数据调查
1. 汇总数据
登录到听云的后台办理页面,首要咱们可以看到汇总的监测数据,图表的作用仍是不错的,鼠标放到每个数据点上会显现具体的数据。
整体看来,分为两大类,一类是运用交互功用,这类首要是监测 UI 呼应状况,会给出 view 加载,以及 layout 的时刻汇总。假如发现某一项参数出现异常,那或许便是需求重构 UI 的信号了。另一类是网络功用,包括网络恳求的呼应时刻等。
2. Web View
重要的东西最先讲,这个部分是听云现在最有特征的部分(好像是首家这么做的,现在还没在其他的相似服务里看到这个功用)。一般咱们进行网络功用监测的时分,给出的是整个网络恳求的状况,这在浏览器里面来说,整个网络恳求其实也便是页面的恳求,两者没有差异。而到了 App 里,同样是 http 恳求,有或许是来自 web service 的调用,也或许是来自 web view 加载页面。而后者正好是咱们讲的 Hybrid App 的首要完成办法。听云的这个条目便是彻底只给出 web view 所进行的恳求状况,换句话说,这是咱们用来监测 Hybrid App 网络功用的最好数据。
(1)HTTP恳求
这儿有一切 web view 所加载的页面的汇总数据。
(2)页面加载
听云除了给出网络功用的数据,这儿还很交心的给出了页面加载的汇总数据,要知道现在的网页是有或许十分杂乱,包括许多页面元素的,在桌面端问题或许不显着,但在移动端,太杂乱的作用或许会大大的拖慢加载速度,影响用户体会。依据这儿给出的页面加载数据,就可以有针对性的去优化网页了。
3. 网络
这个条目首要是 App 的一切网络恳求的数据。
(1)拓补图
这首要是一个分类汇总的数据,可以别离查看是自己的 App 所以及第三方服务所发送的网络恳求的汇总数据。
(2)HTTP恳求
望文生义,这儿是一切 http 恳求的具体数据,别离显现了呼应最慢的主机,以及吞吐量最高的主机。
(3)地域
这个条目比较有意思,用色彩的办法标明出了世界各国的均匀呼应时刻,点击对应的国家还可以持续进入到下一级,终究可以进入到具体的网络数据剖析页面。
(4)组合剖析
这个页面在我国的网络环境下是十分有用的,它可以依据运营商,地域,接入办法来给出汇总数据。要知道我国的网络环境十分杂乱,不同运营商之间,乃至同一运营商在不同的区域网络互通状况会相差十分大。有了这儿的数据,就可以有针对性的去布置服务器,优化网络体会。
4. 交互
进入交互剖析具体项
在这儿咱们可以具体的看到 ViewController 以及 View 的每一个体系函数的调用时刻,经过这个数据就可以十分好的剖析是哪个一个 ViewController 出了问题,对应的去重构就可以了。
交互剖析下边的几项是经过必定的条件来看 UI 交互的具体数据,可以经过版别进行过滤,这样就可以便利的过滤掉现已把问题修正掉了的版别。还可以经过操作体系(iOS/Android)和设备来看各自的交互呼应的数据。
5. 其他
除了功用剖析,听云的数据里也有常见的溃散数据,活泼数以及事情监测等。这儿就不具体展开了
七 总结
Hybrid App 在某些特定场景是十分有用的,但是也的确有它的局限性,特别是对交互要求很高的当地,运用它是不太适宜,究竟它仍是根据网页技能。不过html5在移动端的开展也十分敏捷,或许会有更好的未来也说不定。总归把握这个技能是不会错的。别的因为网页端很或许会成为咱们功用瓶颈,所以要不时留意测验相关部分的功用体现,也主张运用一些运用功用监测的第三方服务。这样可以更好的定位产品环境的问题。