[转]iOS hybrid App 的实现原理及性能监测

转自:http://www.cocoachina.com/ios/20151118/14270.html

iOS hybrid App 的实现原理及性能监测

2015-11-18 11:39 编辑: lansekuangtu 分类:iOS开发 来源:CocoaChina

1 2571

iOS原理hybrid app性能监测

作者董一凡自述:作为一名写了十年代码的程序员,目前我最擅长的领域是移动平台的客户端开发,在移动领域的开发时间超过七年,前前后后涉猎过很多个平台。随着大部分移动平台自己走向死亡,现在我也主要专注在了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 函数

假设我们的网页中有如下代码


1

2

3

4

5

[script type="text/javascript"]

    function myFunc() {

        return "Text from web"

    }

[/script]

原生代码可以用如下方式调用 myFunc()


1

NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"myFunc()"];

在这里 result 就等于 Text from web

2. 网页中的 JavaScript 调用系统的原生代码

这一步比上边的要复杂一些,iOS 不像 Android 可以直接给网页中的 JavaScript 函数注入一个原生代码的接口。这里我们会用一个比较曲折的方式来实现。

假设 Objective-C 的类里有一个方法


1

2

-(void)nativeFunction:(NSString*)args {

}

JavaScript 里我们用下边的方法来最终调用到上边这个方法


1

window.JSBridge.callFunction("callNativeFunction""some data");

在我们的页面里,是没有 JSBridge.callFunction 存在的,这一步我们要在原生代码端注入。

在 webView 的 delegate 的 - (void)webViewDidFinishLoad:(UIWebView *)webView 里我们用下边的方式注入 JavaScript


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

NSString *js = @"(function() {\

window.JSBridge = {};\

window.JSBridge.callFunction = function(functionName, args){\

var url = \"bridge-js://invoke?\";\

var callInfo = {};\

callInfo.functionname = functionName;\

if (args)\

{\

callInfo.args = args;\

}\

url += JSON.stringify(callInfo);\

var rootElm = document.documentElement;\

var iFrame = document.createElement(\"IFRAME\");\

iFrame.setAttribute(\"src\",url);\

rootElm.appendChild(iFrame);\

iFrame.parentNode.removeChild(iFrame);\

};\

return true;\

})();";

[webView stringByEvaluatingJavaScriptFromString: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,在这个方法里我们做如下处理


1

2

3

NSURL *url = [request URL];

NSString *urlStr = url.absoluteString;

return [self processURL:urlStr];

processURL 函数如下


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

-(BOOL) processURL:(NSString *) url

{

    NSString *urlStr = [NSString stringWithString:url];

    NSString *protocolPrefix = @"bridge-js://invoke?";

    if ([[urlStr lowercaseString] hasPrefix:protocolPrefix])

    {

        urlStr = [urlStr substringFromIndex:protocolPrefix.length];

        urlStr = [urlStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        NSError *jsonError;

        NSDictionary *callInfo = [NSJSONSerialization

                                JSONObjectWithData:[urlStr dataUsingEncoding:NSUTF8StringEncoding]

                                options:kNilOptions

                                error:&jsonError];

        NSString *functionName = [callInfo objectForKey:@"functionname"];

        NSString * args = [callInfo objectForKey:@"args"];

        if ([functionName isEqualToString:@"callNativeFunction"]) {

            [self nativeFunction:args];

        }

        return NO;

    }

    return YES;

}

从 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 探针的头文件


1

#import

最后将 main.m 中加入


1

[NBSAppAgent startWithAppID:App_Key];

代码一般为下边的样子


1

2

3

4

5

6

int main(int argc, char * argv[]) {

@autoreleasepool {

    [NBSAppAgent startWithAppID:App_Key];

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

    }

}

这样整个集成工作就完成了。启动 App,如果在 Log 日志中有如下内容显示就表示代码集成成功


1

2

3

NBSAppAgent 2.2.2.1

---->start!

Success to connect to NBSSERVER

六 听云监测数据观察

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在移动端的发展也非常迅速,也许会有更好的未来也说不定。总之掌握这个技术是不会错的。另外由于网页端很可能会成为我们性能瓶颈,所以要时时注意测试相关部分的性能表现,也建议使用一些应用性能监测的第三方服务。这样能够更好的定位产品环境的问题。

时间: 2024-08-19 21:04:48

[转]iOS hybrid App 的实现原理及性能监测的相关文章

优化Recorder H5录音:可边录边转码上传服务器,支持微信提供Android IOS Hybrid App源码

目录 一.Recorder H5录音库的特性 (1)浏览器支持 (2)功能支持 二.使用预览截图 (1)移动端H5 (2)IOS Hybrid App (3)Android Hybrid App 三.应用场景 四.优化过程记录 (1)为什么要升级优化 (2)开始使用Web Worker加速转码 (3)剩下的问题 五.Hybrid App存在的意义 六.更多支持 Recorder H5 GitHub开源库随着支持功能的增多,音频转码处理效率渐渐的跟不上需求了,近期抽时间对音频转码部分进行了升级优化

iOS开发 - App程序启动原理

Info.plist和pch文件的作用 建立一个工程后,会在Supporting files文件夹下看到一个"工程名-Info.plist"的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 在旧版本Xcode创建的工程中,这个配置文件的名字就叫"Info.plist" 项目中其他Plist文件不能带有"Info"这个字眼,不然会被错认为是传说中非常重要的"Info.plist" 项目中还有一个InfoPlist.st

二. Weinre 调试 IOS Hybrid APP

1. 安装weinre npm install –g weinre 2. 打开 weinre -httpPort 8080 -boundHost -all- httpPort 监听端口 boundHost 绑定主机 eg. weinre -httpPort 8080 -boundHost 172.16.144.11 成功后会出现相应信息(不要关掉cmd) c:\Users\xxxxx>weinre -httpPort 8080 -boundHost 172.16.144.112014-12-11

HybridApp解决方案_No1_混合模式(Hybrid)App开发概述

1.1.     APP三种开发模式 智能手机之普及不用多说,手机APP渗投到各个行业:电商(淘宝.京东等).金融(各手机行业.P2P借贷等).医疗(智慧医疗).交通(滴滴.Uber等).教育(慕课网等).餐饮(饿了吗.美团等)……反正只要是个企业,无论规模大小,都已经订制或将要订制自己的APP.这么多APP无外乎就三种模式:Native App.Web App.Hybrid App. 1.1.1.     Native App Native App,原生APP,使用原生(即Android或iO

Hybrid APP基础篇(四)->JSBridge的原理

说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:JS如何调用Native 第三步:Native如何得知api被调用 第四步:分析url-参数和回调的格式 第五步:Native如何调用JS 第六步:H5中api方法的注册以及格式 进一步完善JSBridge方案 思路 实现 注意 完整的JSBridge 完整调用流程图 另外实现:不采用url sche

Hybrid App Development: 二、关于造轮子以及在Xcode iOS应用开发中加入Cordova

转载请注明出处:http://www.cnblogs.com/xdxer/p/4111552.html [ctrl+左键点击图片可以查看原图] 在上一篇关于Hybrid App Development的文章中,我讨论了一下在iOS下UIWebView的使用方法.但是光使用一个UIWebView所提供的功能还是完全不能满足我们的需求.   关于造轮子的思考: 在UIKit中的UIWebView虽然已经提供了很多功能了,比如JavaScript和Objc之间的通信.但是考虑到一个问题,如果在Hybr

【如何快速的开发一个完整的iOS直播app】(原理篇)

一.个人见解(直播难与易) 直播难:个人认为要想把直播从零开始做出来,绝对是牛逼中的牛逼,大牛中的大牛,因为直播中运用到的技术难点非常之多,视频/音频处理,图形处理,视频/音频压缩,CDN分发,即时通讯等技术,每一个技术都够你学几年的. 直播易:已经有各个领域的大牛,封装好了许多牛逼的框架,我们只需要用别人写好的框架,就能快速的搭建一个直播app,也就是传说中的站在大牛肩膀上编程. 二.了解直播 热门直播产品 映客,斗鱼,熊猫,虎牙,花椒等等 直播效果图 直播效果.jpeg 1.一个完整直播ap

如何快速的开发一个完整的iOS直播app(原理篇)

前言 大半年没写博客了,但我一直关注着互联网的动向,最近会研究很多东西,并分享,今年移动直播行业的兴起,诞生了一大批网红,甚至明星也开始直播了,因此不得不跟上时代的步伐,由于第一次接触的原因,因此花了很多时间了解直播,整理了直播的原理,当前只是原理篇,后续会持续发布实战篇,教你从零开始搭建一个完整的iOS直播app,希望能帮助到更多的人更快的了解直播. 一.个人见解(直播难与易) 直播难:个人认为要想把直播从零开始做出来,绝对是牛逼中的牛逼,大牛中的大牛,因为直播中运用到的技术难点非常之多,视频

转: 跨终端Web之Hybrid App

转:  http://www.infoq.com/cn/articles/hybrid-app 编者按:InfoQ开设新栏目“品味书香”,精选技术书籍的精彩章节,以及分享看完书留下的思考和收获,欢迎大家关注.本文节选自徐凯著<跨终端Web>第八章“Hybrid App”,主要讲述Hybrid App的发展现状以及技术实现,最后还介绍了两种主流Hybrid开发框架PhoneGap/Cordova和Titanium. Native App(以下简称Native)和Mobile Web(以下简称We