iOS组件化实践之路
前言
随着应用需求逐步迭代,随着应用逐步庞大,开发人员越来越多和繁杂。为了更好的管理项目,项目组件化逐渐走入了iOS开发者视野,通过组件化方式,理想状态是:我们能使模块之间完全解耦,让独立模块和独立功能能单独运行,这样做有哪些好处?
- 模块完全独立和解耦,方便不同团队之间进行协作
- 庞大的工程拆分为了多个子工程,编译和运行时间大大缩短
- 方便实现模块的版本控制
- 方便实现动态配置化,由于模块之间的独立性,在业务逐渐丰富情况下,我们可以通过配置中心,对APP进行配置,控制模块的动态的添加和移除。
- ……
当前主流方案
2016.03.10 蘑菇街App的组件化之路(git文档被删除,见此)
2016.03.13 iOS应用架构谈 组件化方案
2016.03.14 蘑菇街App的组件化之路·续
2016.03.18 iOS组件化方案探索
2016.03.21 围观神仙打架,反革命工程师《iOS应用架构谈 组件化方案》和蘑菇街Limboy的《蘑菇街 App 的组件化之路》的阅读指导
通过这几篇撕逼的文章,我们对组件化有了初步的认识和了解,对组件解耦方式有自己的想法。在这里我的重点不是组件之间是如何调用的,不管怎么调用,这只是组件化的其中一部分,而组件化还有很多工作需要做。
组件化实践
业务划分
看了许多文章,我们当然跃跃欲试,下面我便以一个简化的Demo为例,实践组件化。我们以一个简单的淘宝电商Demo作为业务场景,这种最基础的电商场景大家都非常熟悉,我们对Demo进行初略的模块划分:
- BaseEnv模块:登录,网关,数据库,JSBridge,基础Catagory,Util等
- Index业务模块:电商首页模块
- Search业务模块:电商搜索模块
- ProductDetail业务模块: 商品详情模块* Cart业务模块:购物车模块
- ……
大致的结构图如下:
工程搭建
我们可以利用CocoaPods私有库的方式,对不同模块进行集成。
初始化模块
➜ pod lib create ZFIndex
通过这条命令,能生成模块基础代码和.podspec文件,我们需要关心的如下几点!
-
Example
:子工程运行工程,以后的模块开发调试都在此进行,而不是在主工程 -
ZFIndex
: 该模块核心逻辑代码 -
podspec
:该模块作为spec提供给外部使用的配置文件
下面看下podspec
文件内容
#
# Be sure to run `pod lib lint ZFIndex.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'ZFIndex'
s.version = '0.1.0'
s.summary = 'A short description of ZFIndex.'
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://github.com/<GITHUB_USERNAME>/ZFIndex'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'zf' => 'zf@xxx.com' }
s.source = { :git => 'https://github.com/<GITHUB_USERNAME>/ZFIndex.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '8.0'
s.source_files = 'ZFIndex/Classes/**/*'
# s.resource_bundles = {
# 'ZFIndex' => ['ZFIndex/Assets/*.png']
# }
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
end
这部分代码是ruby
写的,具体实现方案后面会进行分析,我们先明白几个关键点:
-
name
: pod名称 -
version
: pod版本号 -
source
: pod对应的git地址 -
source_files
: pod对应的源码文件 -
resource_bundles
: pod工程对应的资源文件 -
frameworks
: pod以framework方式提供需要 -
public_header_files
: pod以framework方式提供需要
主工程引入
主工程通过Podfile
的方式引入,因为现在模块是存在本地的,因此我们使用本地相对路径的方式引入:
Podfile
文件:
require 'cocoapods-multithread-installpod'
platform :ios, '8.0'
target 'ZFModuleDemo' do
pod 'ZFIndex', :path=> '../ZFIndex/'
end
最终工程目录如下图:
这样最简易的组件化工程环境已经搭建好了,我们可以开始进行模块开发。
问题
当然,在实践过程中,我们还会遇到很多问题,在后面的文章中我会逐个进行描述。
问题1: 组件化-Bundle资源图片读取
问题2: 组件化-子模块Example工程环境初始化
问题3: 组件化-本地工程引入方式改为git远程工程