使用多target来构建大量相似App
转自 come from : http://devtang.com/blog/2013/10/17/the-tech-detail-of-ape-client-1/
猿题库iOS客户端的技术细节(一):使用多target来构建大量相似App
Oct 17th, 2013
前言
本人今年主要在负责猿题库iOS客户端的开发,本文旨在通过分享猿题库iOS客户端开发过程中的技术细节,达到总结和交流的目的。
这是本技术分享系列文章的第一篇。本文涉及的技术细节是:采用多Target编译方案来实现多个相似App的开发,以保证我们能够快速地推出多个相似课程的客户端。
问题描述
今年春节后,我们对外发布了应用“猿题库-公务员考试行测”,接着我们就开始一个个发布猿题库系列课程应用。到现在半年多过去了,我们一共对外发布了8款应用(如下图所示)。

这些课程,随了“猿题库-公务员考试申论”和其它课程不一样之外,另外7个课程都有着相似,但是又不完全相同的功能和界面。
这些应用的相同点包括:
- 基本相同的注册和登录以及首页逻辑和界面(只是背景图片不一样而已)。
- 相同的做题逻辑和界面。
- 基本相同的答题报告显示界面。
- 基本相同的能力评估报告界面。
不同点主要包括:
- 应用图标,启动画面,应用启动后的首页都不一样。
- 有些课程(例如公务员考试和高考)是有目标考试的概念,不同的目标考试大纲是不一样的。拿高考来举例,北京的高考和上海的高考,就有着完全不一样的考试大纲。高考的文科和理科,又有着完全不同的考试科目。
- 有些课程会有一些自定义的界面,例如高考的应用可以设置昵称,有些课程的真题练习中是有推荐真题模块的,而有些课程又没有。
- 有些课程有扫描答题卡功能,有些课程有考前冲刺功能,有些课程有大题专项查看功能,而有些课程又没有上述功能。另外还有一些微小细节,但是解决方法和类似,所以就不一一展开说明。
技术解决方案
我们的技术解决方案主要说来分4步:
- 通过抽取子项目,构建可复用的大模块。
- 通过多Target编译的方式,不同课程的在编译时,采用不同的资源文件和源文件。
- 在第2步的基础上,在项目中创建配置用的Config类,然后在不同Target各自的配置文件中设置不同的Config值。实现课程的差异化界面。
- 从不同的xib中加载界面。
抽取子项目
我们首先做的是抽取子项目,从“猿题库司法考试客户端”开始,我们将可以重用的模块一一抽取出来,以git submodule的形式组织到项目中。这个抽取过程在开发完猿题库司法考试客户端之后,基本成型了。我们抽取的submodule主要分为4部分:
- UI Common,涉及可复用的登录界面,注册界面,付费界面,NPS界面,意见反馈界面,关于界面,扫描答题卡界面。另外,我们将一些可复用的UI风格控件也抽取成了相应的静态工厂方法,用于生成统一风格的按钮、背景以及状态栏等。
- Core Common,涉及可复用的底层模块。包括网络请求模块,自己封装的Core Text渲染引擎,缓存模块,一些静态util方法等。
- Lib Common,所有第三方的开源库依赖,有部分代码根据我们的需求做了修改和定制。
- Scan Common, 答题卡扫描识别算法模块,实现核心的扫描算法。
以上只是粗粒度划分,这些模块化的子项目可能在以后被重用,例如Core Common完全就可以复用在任何其它项目中。
构造多个编译Target
抽取完子项目以后,我们采用多target的方式,将不同课程中的同名资源文件打包进各自的Target中,最后所有课程在一个工程项目中,如下图所示:

先简单介绍一下Xcode中target的概念,苹果在文档中写道:
Targets that define the products to build. A target organizes the files and instructions needed to build a product into a sequence of build actions that can be taken.”
在Xcode的一个项目中,可以允许建立多个编译的target,每个target代表着最终编译出来的一个App文件,在每个target中,可以添加不同的编译源文件和资源文件。最终,通过我们在不同target之间,修改其 Copy Bundle Resources 和 Compile Sources 配置,使课程之间的差异性得到实现。我们具体的配置方案如下:
我们的每个课程的资源文件都具有相同的文件名,例如首页背景都叫 HomeBackgroundBg.png ,由于每个课程背景不一样,所以我们在工程中,每一个课程target下,通过修改
Copy Bundle Resources,使其都配置有不同的(但是同名) HomeBackgroundBg.png 。这样的好处是,在代码逻辑层面,我们可以完全不用处理课程间资源文件的差异性问题。资源文件的差异性都是通过配置文件来保证的。对于文案一类的差别,我们通过修改
Compile Sources,使不同的课程有着不同的文案定义文件。通过这样,我们使不同课程有了不同的文案。另外包括后台网络接口的差异性问题,统计项的差异性问题,也都是这样处理的。
Config类
最后,我们使用Config类来完成交互和页面UI组件差异性问题。拿能力评估报告页面来说,不同的课程的页面都有一些差异。我们在公共层的代码中 将这些逻辑全部实现,具体的UI在呈现时,通过读取相关的Config类来决定具体如何展示。这样,我们只需要在第2步提供的各个课程的差异性源文件中, 完成Config类的配置即可。
从不同的xib中加载界面
有些时候,我们仅仅需要的是UI界面排列方式不一样,其它交互逻辑完全一样。对于这种需求,我们尝试同一个view对应有多个xib,然后通过上一 步的Config类的信息,来加载不同的xib界面。这样所有的差异性都在不同的xib中解决了,对controller层可以完全透明。
下图是我们报告页面的xib界面,分为:高考课程、有目标考试的课程、没有目标考试的课程三种。由于这3个界面的后台逻辑和交互逻辑都一样,我们通过3个xib来实现它们之间差异性的部分。

以下是view加载对应的xib的代码逻辑:
1 |
|
总结
通过多target编译方案,我们可以很方便的实现多个相似App的开发,以保证我们能够快速地推出多个相似课程的客户端。同时,由于在一个工程中,我们也可以方便地测试新的代码逻辑在各个课程下是否正常。
该方案可以用来解决“维护大量逻辑相似但是又有细微不同的应用”的需求,希望本文能给业界同行一些帮助。
使用多target来构建大量相似App的更多相关文章
- “使用多target来构建大量相似App”,唐巧大神理论验证(附工程代码地址)
无意间看到巧神的文章时,感觉非常兴奋,此文章正好解决了公司目前项目的痛点. 读到以下关键一段时,不甚明了,故自己做了实验分享给有缘人. "我们的每个课程的资源文件都具有相同的文件名,例如首页 ...
- MontageJS:构建现代 Web App 的 HTML5 框架
MontageJS 可以帮助您构建高可扩展性和可维护性的 HTML5 应用.有了 MontageJS,开发人员可以创建可重用的用户界面组件和模块,组件和控制器之间的绑定属性,并且同步 DOM 查询和更 ...
- Android TV开发总结(六)构建一个TV app的直播节目实例
请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...
- Android TV开发总结(七)构建一个TV app中的剧集列表控件
原文:Android TV开发总结(七)构建一个TV app中的剧集列表控件 版权声明:我已委托"维权骑士"(rightknights.com)为我的文章进行维权行动.转载务必转载 ...
- Android TV开发总结(一)构建一个TV app前要知道的事儿
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...
- .NET Core初体验 在window上构建第一个app
ASP.NET Core 是一个跨平台,高性能的开源框架,用于构建现代化的,基于云的互联网应用程序.使用 ASP.NET Core ,您可以: 构建Web应用程序和服务,IoT应用程序和移动后端. 在 ...
- Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...
- 第5章 使用MUI与H5+构建移动端app
H5+是JS封装的工具集合,通过H5+我们就可以使用JS的方式去调用到我们手机端上的一些原生的组件. http://dev.dcloud.net.cn/mui/ http://dev.dcloud.n ...
- 使用HTML5构建iOS原生APP(2)
本文转载至 http://ju.outofmemory.cn/entry/18807 有时候我们在内嵌的webview中希望点击一个链接之后,触发iOS原生事件,而不是webview内页面跳转(因为w ...
随机推荐
- Mysql5.7.19压缩版安装步骤及踩过的坑
安装Mysql5.7.19压缩版 一:下载压缩包 1.从MySQL官网下载MySQL Community Server 5.7.19,此版本为免费版. 2.下载完成之后解压缩,打开之后文件夹如下: ...
- debian 9 安装后需做的几件事
debian 9 安装后需做的几件事 安装环境:X86 >> Debian 9 Linux/GNU apt源更新 注意连上有线网络 刚安装好的debian系统中,/etc/apt/sour ...
- ajax上传进度条
<script type="text/javascript"> function register(){ var frm = document.getElementBy ...
- Dynamics CRM2016 Web API之Expand related entities & $ref & $count
本篇介绍两个关于1:N关系中通过主实体取关联子实体的api,这两个api会常常被用到并且比原来的odata方式更加方便.之前假设我们要取主实体下全部的关联实体的记录都是通过Retrieve Multi ...
- iCarousel——在iOS和Mac OS应用中实现3D CoverFlow旋转木马效果的开源类库
前言 iCarousel一个简单.可高度定制的3D CoverFlow开源类库,旨在简化在 iPhone, iPad和Mac OS中生成各种类型的cover flow(视图切换)效果(分页.滚动视图) ...
- GO语言学习(二)Windows 平台下 LiteIDE 的安装和使用
1. 安装 Go 语言并设置环境变量 参考GO语言学习(一) 2. MinGW 的下载和安装 Windows 下的 Go 调试还需要安装 MinGW. 2.1 下载安装工具的安装 最新版本下载安装工具 ...
- 【Eclipse提高开发速度-插件篇】Checkstyle的使用
1.CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发者遵守某些编码规范的工具. CheckStyle提供了大部分功能都是对于代码规范的检查 CheckStyle检验 ...
- Android OnGestureListener用法 识别用户手势 左右滑动
Android可以识别用户的手势(即用户用手指滑动的方向),通过用户不同的手势,从而做出不同的处理 需要使用OnGestureListener 比如说看电子书的时候翻页,或者要滑动一些其他内容 直接上 ...
- python3中numpy函数的argsort()
摘自:https://www.cnblogs.com/yushuo1990/p/5880041.html argsort函数argsort函数返回的是数组值从小到大的索引值 Examples----- ...
- PHP SPL标准库之数据结构栈(SplStack)介绍(基础array已经可以解决很多问题了,现在开始解决问题)
PHP SPL标准库之数据结构栈(SplStack)介绍(基础array已经可以解决很多问题了,现在开始解决问题) 一.总结 SplStack就是继承双链表(SplDoublyLinkedList)实 ...