概况
众所周知组件化是个好东西,它把项目拆分成多个模块,让每个模块能够独立出来解除各个模块之间的耦合性,作为每个独立的模块不仅仅能够使用组合的方式去组建各个不同的功能组合(前提是各个组件划分的颗粒度只要足够小),而且能够独立出来运行,在开发运行以及测试中极大的提升了开发效率,让整个项目在维护上变得方便,而且整个项目的扩展性变得更健壮。
在 iOS
中可以通过 Pods
管理各个组件,Pods
的原理不做介绍,重点说在制作组件的方法与实践。
相信大部分项目在创建的时候,可能都没有将组件化的工程架构放入其中,因为起初的项目可能并不大,用简单的多人协作开发模式加上代码架构模式(如 MVC/MVVM/MVP
等)进行项目的开发,这样速度快,开发周期短,更符合敏捷开发的原则,所以一开始可能并没过多的去考虑组件化。但是随着项目的不断壮大,项目中不断加入新的功能,慢慢的就会发现项目的编译时间越来越长,各个功能的耦合性也变得越来越高,最为头疼的是,假如有需求要求某个功能模块抽出来单独的去集成到公司的另一个产品中,由于一开始的项目架构设计造成的代码的关联耦合,根本无法进行模块化的抽出,是不是得崩溃到哭。每一次痛苦的历程总会冲击出新的解决方案,于是组件化的搭建开始了。
使用 Pods
搭建组件的背景分两种:
1.正在开发的项目转变成组件
2.空白项目,从0到1构建组件
对于第一种,老项目迁移成组件架构模式,可以分成三步:
1.重构项目,分离出各个模块,划分清楚组件构件(可以通过使用路由思想完成组件通信的解耦)
2.抽出组件分离出主项目,将组件制作成Pods
管理的私有库,并发布模块组件版本
3.主项目使用Pods
进行各个组件的集成
第二种就相对简单点了,省去了第一种的第一步(这是个耗时耗力的过程),直接在创建整个项目的时候构建出各个组件,于是就变成了两步:
1.将组件制作成
Pods
管理的私有库,并发布模块组件版本
2.主项目使用Pods
进行各个组件的集成
由于 Pods
在创建私有库的管理时候需要绑定git
实现创建,所以整个项目需要依托于 git 管理。以下的搭建是在当前项目处于 git
管理中的操作。由于 github
创建私有库需要 money,所以这里我选用了其他的git
托管,有很多代码托管网站可以使用,我用的是 Coding
。
搭建简述
Pods
的搭建组件步骤如下:
1.本地创建私有的
repo
仓库(需要与远程git
托管地址绑定)
2.创建并配置当前的pod
的.spec
文件
3.验证当前的.spec
的有效性
4.发布当前的pod
版本(默认会推送到远端)
搭建详情
- 本地创建私有的
repo
仓库
打开term
控制台,通过执行如下命令进行本地私有的repo
的创建
pod repo add LCProjectSpecs https://git.coding.net/lccdl/LCModulLearnDemo.git
执行完成如下:
执行命令之后,我们可以打开本地的 repo
查看私有的库是否创建成功,使用如下命令:
cd ~/.cocoapods/repos
结果如下:
- 创建并配置当前的
pod
的.spec
文件
在创建私有的pod
之前我们需要进入当前的模块所在的文件夹,然后执行如下命令进行.sepc
文件的创建
pod spec create https://git.coding.net/lccdl/LCModulLearnDemo.git
执行完成之后,当前目录下会出现一个.spec 文件,用编辑工具打开它,它是一个ruby
格式的文件配置可以按照如 下进行配置
Pod::Spec.new do |s|
s.name = "LCModulOne" #当前的 pod 名字
s.version = "0.1.2" #pod版本
s.summary = "测试" #描述
s.description = <<-DESC
模块化开发
DESC
s.homepage = "https://coding.net/u/lccdl/p/LCModulLearnDemo"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "lccdl" => "lcc_dl@163.com" }
s.platform = :ios, "8.0"
s.source = { :git => "https://git.coding.net/lccdl/LCModulLearnDemo.git", :tag => s.version.to_s }
s.source_files = "LCModulOne/LCModulOne/Classes/*"
end
- 验证
specs
的配置是否正确
这里可以通过两个命令来进行验证,两个命令分别针对本地与远端的验证
pod lib lint #验证本地 pod 配置是否正确
pod spec lint #验证远端 pod 配置是否正确
这里有一个坑点,就是可能在本地验证 pod lib lint
的时候一点问题没有,但是在进行远程 pod spec lint
验证的时候会出现如下的错误提示:
这个问题可能是source_files
对应的远程的路径没有填写正确造成的,本地验证的时候,source_files
对应的路径的起始路径是当前路径,而source_files
在远程验证时对应的目录的根目录是 git
的根目录(不是当前的 spec
文件所在的目录了),所以可能在验证当前的远程的目录的时候可能会出现问题,只要把目录的路径写对就好了。
- 发布
pod
管理的组件版本
验证成功之后,可以通过以下命令进行当前版本的发布。
pod repo push LCModulDemoSpecs LCModulOne.podspec #LCModulDemoSpecs 是本地的私有库 LCModulOne.podspec 当前的管理模块的 pod
当验证 pod
配置文件没有问题之后,会将当前 pod
发布到当前的私有库LCModulDemoSpecs
中,同时此时会默认推送到 git
的master
分支中(无论当前处于哪个分支下,都会推送到主分支)。这一步完成之后,我们就可以通过搜索 pods
来进行正常的 pod
的模块依赖了。
- 组合不同的模块进行不同模块的开发
一旦发布各自的模块版本之后,那么参与项目的其他的人就可以通过pod
来加载不同的模块功能进行开发了,不过因为是私有库,所以在进行pod
安装的时候,需要指定私有库的地址,使用的时候编辑podfile
,内容如下:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
source '[https://git.coding.net/lccdl/LCModulLearnDemo.git](https://git.coding.net/lccdl/LCModulLearnDemo.git)'
target 'LCMainRootModul' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for LCMainRootModul
pod 'LCModulOne'
end
以上说的是已有项目的使用 pod 进行组件化,如果是新开发的某个模块需要进行 pod 组件化,可以通过 pod 自带的一个命令去创建,这样创建的组件就自带 Demo 工程以及配置文件了。命令如下:
pod lib create podTestLibrary
创建的时候会问你几个问题,直接按需要回答就好了,四个问题如下:
1.是否需要例子工程(建议保留,开发组件的时候需要用到)
2.根据需要选择一个测试类型
3.是否要基于View
进行测试
4.类的前缀
创建完成以后,目录层级如下:
开发迭代维护
在开发组件过程实际就是迭代 Pods
库的过程,我们在每个组件的实例工程中进行当前的开发,开发完成后通过发布组件的版本既可。在开发的时候由于组件在开发过程中,所以我们在开发自己的组件的时候,可以通过设置本地路径的形式去关联正在开发的组件文件,如下:
use_frameworks!
target 'LCModulOne_Example' do
pod 'LCModulOne', :path => '../'
target 'LCModulOne_Tests' do
inherit! :search_paths
end
end
当前的工程 update
之后,例子工程中就有了正在开发的pod
了,如下所示:
这里要注意,每次在往开发的 Pods
中添加文件的之后都需要通过 pod update
命令更新本地的正在开发的 Pods
, 否则实例工程中可能出现找不到当前的文件。
在利用 pod
进行组件化的迁移过程中,由于在进行组件发布的时候会默认推送到当前组件所在的 git
的 master
分支,如果此时 master
分支作为线上发布版本的分支的话,我们是不希望该分支有任何的代码入侵的,响应的我们可能希望当前的pod 发布只在当前的开发环境分支进行,maste
r 不掺杂任何开发过程中所出现的代码,为此,可以通过创建两个 git 的方案去解决这样的问题,一个 git
作为组件的开发版环境,另一个 git
专门作为发布环境只进行组件的集成与发布。如下图展示:
灵活的组件迁移组合方案
相信在进行组件化的工程项目一般都已经很庞大了,如果进行全盘迁移的话,时间上可能很长久,再者伴随的不定风险或许很大(涉及到项目的重构),所以结合之前各自项目的架构特点再去联合组件化思想对项目进行迁移是明智之举。组件化的根本目的是解耦项目各个模块间的耦合度,所以顺着这个思想,找出项目中耦合度最高的模块进行迁移才是重中之重。
其实在一般工程在起初创建的时候都已经做到了降低耦合度的构建方式,例如将一些工具类、或者通用的模块设计成项目的底层构件服务于上层模块,这些底层构件不依赖与上层模块,就已经做到了很好的降低耦合的目的,这样的设计有着层级架构
的特点,所以通过层级架构+组件化
构建的方式灵活的去降低项目的模块间的耦合性也是很实际化的选择,而且对比全盘迁移组件化时间维度
与可控性
上要占据更大的优势。总之,对于不同的项目要合理的利用当前项目架构特点再去与组件化思想相结合来进行才是灵活变通的根本。
组件化Pods
构想
一旦使用了 pod
构建自己的组件之后,会发现真的停不下来,正式因为组件化的构建思想,就会很自然的想到利用 Pods
去将自己工程中通用的模块做成一个组件,然后通过 git
进行管理,一旦去接受一个新的项目的时候,完全可以通过pod
将需要的不同模块的东西引入到新的项目中(例如网络库的封装、基本工具类的封装、常用的宏脚本
),开发效率也就得到了大大的提高,而且体现了一种前期积累后期建楼的生活哲理不是。
参考资料:
http://www.cocoachina.com/ios/20150228/11206.html
http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec/
https://www.cnblogs.com/oc-bowen/p/5885476.html
https://www.zybuluo.com/qidiandasheng/note/392639