58同城iOS客户端Hybrid框架探索

作者:杜艳新,刘文军。58同城iOS高级研发工程师,专注于App Hybrid框架的架构研发,主导了58同城App的Hybird混合研发的系统架构以及研发。
责编:唐小引,欢迎技术投稿、约稿、给文章纠错,请发送邮件至tangxy@csdn.net。
本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅《程序员》

58同城iOS客户端的Hybrid框架在最初设计和演进的过程中,遇到了许多问题。为此,整个Hybrid框架产生了很大的变化。本文作者将遇到的典型问题进行了总结,并重点介绍58 iOS采用的解决方案,希望能给读者搭建自己的Hybrid框架提供一些参考。

引言

Hybrid App是指同时使用Native与Web的App。Native界面具有良好的用户体验,但是不易动态改变,且开发成本较高。对于变动较大的页面,使用Web来实现是一个比较好的选择,所以,目前很多主流App都采用Native与Web混合的方式搭建。58同城客户端上线不久即采用了Hybrid方式,至今已有六七年。而iOS客户端的Hybrid框架在最初设计和演进的过程中,随着时间推移和业务需求的不断增加,遇到了许多问题。为了解决它们,整个Hybrid框架产生了很大的变化。本文将遇到的典型问题进行了总结,并重点介绍58 iOS采用的解决方案,希望能给读者搭建自己的Hybrid框架一些参考。主要包括以下四个方面:

1. 通讯方式以及通讯框架

58 App最初采用的Web调用Native的通讯方式是AJAX请求,不仅存在内存泄露问题,且Native在回调给Web结果时无法确定回调给哪个Web View。另外,如何搭建一个简单、实用、扩展性好的Hybrid框架是一个重点内容。这些内容将在通讯部分详细介绍。

2. 缓存原理及缓存框架

提升Web页面响应速度的一个有效手段就是使用缓存。58 iOS客户端如何对Web资源进行缓存以及如何搭建Hybrid缓存框架将在缓存部分介绍。

3. 性能

iOS 8推出了WebKit框架,核心是WKWebView,其在性能上要远优于UIWebView,并且提供了一些新的功能,但遗憾的是WKWebView不支持自定义缓存。我们经过调研和测试发现了一些从UIWebView升级到WKWebView的可行解决方案,将在性能部分重点介绍。

4. 耦合

58 iOS客户端最初的Hybrid框架设计过于简单,导致Web载体页渐渐变得十分臃肿,继承关系十分复杂。耦合部分详细介绍了平稳解决载体页耦合问题的方案。

通讯

Hybrid框架首先要考虑的问题就是Web与Native之间的通讯。苹果在iOS 7系统推出了JavaScriptCore.framework框架,通过该框架可以方便地实现JavaScript与Native的通讯工作。但是在58 App最早引入Hybrid时,需要支持iOS 7以下的系统版本,所以58 App并没有使用JavaScriptCore.framework,而是采用了更原始的方式。

传统的通讯方式(如图1所示)中,Native调用JavaScript代码比较简单,直接使用UIWebView提供的接口stringByEvaluatingJavaScriptFromString:就可以实现。而JavaScript调用Native的功能需要通过拦截请求的方式来实现。即JavaScript发送一个特殊的URL请求,该请求并不是真正的网络访问请求,而是调用Native功能的请求,并传递相关的参数。Native端收到请求后进行判断,如果是功能调URL请求则调用Native的相应功能,而不进行网络访问。

图1  传统的通讯方式流程

图1 传统的通讯方式流程

按照上面的思路,在实现Hybrid通讯时,我们需要考虑以下几个问题:

通讯方式

前端能发起请求的方法有很多种,比如使用window.open()方法、AJAX请求、构造iframe等,甚至于使用img标签的src属性也可以发起请求。58 App最早是使用AJAX请求来发起Native调用的,这种方式在最初支撑了58 App中Hybrid很长一段时间,不过却存在两个很严重的缺陷:

  • 一是内存问题:在iOS 8以前,iOS中内嵌Web页都是通过系统提供的UIWebView来实现的。而在UIWebView中,JavaScript在创建XMLHttpRequest对象发起AJAX请求后,会存在内存泄露问题。在实现的应用中,JavaScript与Native的交互操作是很频繁的,使用XMLHttpRequest会引起比较严重的内存问题。

  • 二是拦截方法:UIWebView中的正常URL请求会触发其代理方法,我们可以在其代理方法中进行拦截。但是AJAX请求是一个异步的数据请求,并不会触发UIWebView的代理方法。我们需要自定义App中的NSURLCache或NSURLProcotol对象,在其中可以拦截到URL请求。但是这种方式有两个问题,一个是当收到功能调用请求时,不易确定是哪个Web View对象发起的调用,回调时也无法确定调用哪个Web View的回调方法。为了解决这个问题,58 App的Hybrid框架维护了一个Web View栈,记录所有视图层中的Web View,前端在发起Native调用时,附加一个Web View的唯一标识信息。在Native需要回调JavaScript方法时,通过Web View的唯一标识信息在Web View栈中找到对应的Web View。另一个是对App的框架结构有影响,Hybrid中的一个简单的调用需要放在App的全局对象进行拦截处理,破坏Hybrid框架的内聚性,违反面向对象设计原则。

iframe称作嵌入式框架,和框架网页类似,它可以把一个网页的框架和内容嵌入在现有的网页中。iframe是在现有的网页中增加一个可以单独载入网页的窗口,通过在HTML页面中创建大小为0的iframe,可以达到在用户完全无感知的情况下发起请求的目的。使用iframe发送请求的代码如下:

var iframe = document.createElement("iframe");
//设置iframe加载的页面链接
iframe.src = “ http://127.0.0.1/NativeFunction?parameters=values”;
//向DOM tree中添加iframe元素,以触发请求
document.body.AppendChild(iframe);
//请求触发后,移除iframe
iframe.parentNode.removeChild(iframe);
iframe = null;

iframe是加载一个新的页面,请求会走UIWebView的代理方法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值