iOS组件化开发之路(CTMediator),涉及到cocoap
以下文章为本人研究组件化之后的理解,对于这一路上的种种不明确问题及查询了好多博客上错误的资料,一路采坑过来有了如下总结,如有错误,欢迎大神指出。
iOS的组件化分为什么?这里注意是分为,什么,不是分,为什么
这还分为什么么?当然。
其实我们平时使用cocoapods的公开库也算是组件化的一种。
一、按照存储方式分
- 本地库
- 远程私有仓库
- 远程公开仓库
自己项目的组件化可以用前两种(1.本地库、2.远程私有仓库)方式。
这几个库有什么区别呢?
本地库
项目和索引文件都存储在你本地,pod之后需要用path配你本地的路径
远程私有仓库
需要给索引文件创建一个仓库,需要给你封装的组件创建一个仓库,将组件打上tag版本关联到索引的文件
远程公开仓库
这个就是我们平时正常引用三方开源框架的方式pod "AFNetworking"啊。。。
二、按照项目结构分
1.单个项目的多个组件
2.多个项目的多个组件
单个项目的多个组件
这个就是你有一个主项目,将登录、新闻详情、购物车等等的功能独立成组件。
多个项目的多个组件
这个就好比有一个项目叫淘宝,你搜索出来一堆天猫的商品,需要跳转到天猫的商品详情页,但是你不能把天猫的代码粘过来呀,更不能把文件拷贝一份过来呀,这个时候怎么办呢,不要慌,叫天猫项目的开发人员将他的商品详情抽成一份组件出来,上传到远程仓库,这个仓库需要创建成私有的,因为自己写的项目可不能随便给公开喽,你在工程里pod一下,天猫的详情页就过来,这个跟公开的库用法一样,其实在项目里直接#import <TmallDetailViewController.h>就可以用了,没毛病。但是,看好了啊,但是来了,这样是不是两个工程就关联上了,这不是我们想要的啊,我们想要的是解耦,将耦合度将到最低最低,此时就要用到CTMediator这个三方库了,用这个路由将两个项目解耦。
理论就说到这里,下面开始实践
等等落了句话,其实按照项目结构分的“单个项目的多个组件”和“多个项目的多个组件”只是叫法上不一样,他们在实践上是一样的,因为登录、新闻详情他们抽出来的单个组件也是在一个独立的项目中,这也是一个单独的项目,只是没有它的主功能罢了。
下面开始真的实践了
这里我只需要讲:本地库 + 路由到页面和远程私有库 + 路由到页面这两个组件化模式。
下面开始操作
好多博客里面都是用 pod lib create 这种直接创建模板工程的方式去创建,但是我不喜欢这样,对于本来不熟的人操作就够乱套的了在加上这一手会更加乱套。
一、本地库创建 + 组件化
1. 首先创建一个空文件夹这里我们起名ShoppingProject,用来容纳我们的主工程和组件工程,放到一起不乱套。

2. 创建主工程

版本号这块要注意一下,所有工程的版本号要设置成一样的,包括一会我们创建的索引文件也要设置成一样的,这里我选的iOS10.0

3. 工程基础代码设置一下还有证书什么的自己配置一下,保证工程可以跑起来
创建好之后应该是这样的


模拟器应该是这样的

4. 创建组件工程,这里我们做登录的组件页LoginComponent

此时创建完成你的ShoppingProject文件夹应该是这样的

5. 配置一下工程的版本号证书及基本设置等等
6. 新建LoginViewController文件夹,继承UIViewController的控制器

7. 设置Appdelegate.m和LoginViewController.m文件


跑起来的模拟器

8. 新建Targets文件夹,继承NSObject创建一个类,名字先跟我起一样的这个地方在路由有映射,所以名字一定要对应取好,这个就是组件工程为主工程开放出来的接口

9. Target_Login中的代码


主工程和组件工程到此就整完了,下面我们开始创建CTMediator的分类工程,这个工程是用来连接主工程与组件工程的桥梁,是我们实现工程解耦的关键一步
10. 创建LoginComponent_Category工程

创建好后的工程目录

11. 配置版本号和证书描述文件啦 等等。。。
12. 配置好后关闭工程,打开终端,我们要为LoginComponent_Category工程通过cocoapods引入三方框架CTMediator
进入到LoginComponent_Category工程目录
$ touch Podfile
编辑Podfile文件
platform :ios, '10.0'
target 'LoginComponent_Category' do
pod 'CTMediator'
end
$ pod install
13. 使用LoginComponent_Category.xcworkspace打开工程,创建对应文件夹及CTMediator的分类

CTMediator+Login.h和CTMediator+Login.m中的代码


这个地方就是这么映射的

三个项目到这里就差不多了,下面我们开始配置podspec,这个就是用来创建pod索引的,有了这个文件才能被别的项目pod进去
14. 打开终端进入LoginComponent工程的根目录
创建索引依赖文件
$ pod spec create LoginComponent
执行之后会在你的工程目录里多出这么一个文件

LoginComponent.podspec文件配置
Pod::Spec.new do |spec|
spec.name = "LoginComponent"
spec.version = "0.0.1"
spec.summary = "A short description of LoginComponent."
#spec.homepage = "http://EXAMPLE/LoginComponent"
spec.author = { "Cloud" => "haohao10987@163.com" }
spec.platform = :ios, "10.0"
#spec.source = { :git => "http://EXAMPLE/LoginComponent.git", :tag => "#{spec.version}" }
spec.source_files = "LoginComponent/LoginComponent/LoginViewController/**/*.{h,m}", "LoginComponent/LoginComponent/Targets/**/*.{h,m}"
end
看到下图中两个画框的文件位置了吗,我们要为这两项配置去创建一个远程的仓库,因为是本地库嘛,我也不想创建,但是这两项不填写正确的在pod install的时候会报错,所以我们需要为它创建一个远程仓库,这里我们创建一个私有的远程仓库,对了,远程仓库我用的码云(这里的远程私有仓库和前面说的远程私有库 + 路由这种配置方法没关系,这里我们只是用了一下库的链接,真正要用到私有库还需要为私有库配置spec的工程和关联索引,不理解没关系,一会我讲远程私有库 + 路由的时候再去理解)

仓库的使用我这里不多做介绍,创建好后自己把项目关联好,在上图红框的位置填入相应链接

传完之后我的项目目录结构就变成这样子的了

修改LoginComponent.podspec文件

15. 修改Shopping工程的Podfile文件

这块是方便你复制粘贴的
platform :ios, '10.0'
target 'Shopping' do
pod 'LoginComponent', :path => "../LoginComponent"
end
16. 终端进入到Shopping文件夹,执行
$ pod install
紧接着在Development Pods就会出现我们的Pods项目中(跟公开库直接在Pod文件夹中不太一样)

到此为止,组件工程已经被我们引入到主工程中了,但是为了解耦,主工程和组件工程不可以直接相互调用,下面我们开始制作“LoginComponent_Category”这个分类组件工程的本地库,然后引入到主工程中。
17. 有了上一次的经验我们先为“LoginComponent_Category”分类组件工程创建它的远程私有仓库

这是关联好之后的目录层级

18. 打开终端,为“LoginComponent_Category”分类组件工程创建podspec项目依赖索引文件
进入到LoginComponent_Category根目录
$ pod spec create LoginComponent_Category
创建好之后的样子

19. 配置LoginComponent_Category.podspec文件

没错,下面这段是方便你复制粘贴的
Pod::Spec.new do |spec|
spec.name = "LoginComponent_Category"
spec.version = "0.0.1"
spec.summary = "A short description of LoginComponent_Category."
spec.homepage = "https://gitee.com/moment_forever/LoginComponent_Category"
spec.author = { "Cloud" => "haohao10987@163.com" }
spec.platform = :ios, "10.0"
spec.source = { :git => "https://gitee.com/moment_forever/LoginComponent_Category.git", :tag => "#{spec.version}" }
spec.source_files = "LoginComponent_Category/LoginComponent_Category/LoginComponent_Category/**/*.{h,m}"
spec.dependency "CTMediator"
end
20. 在主工程的Podfile文件里配置
platform :ios, '10.0'
target 'Shopping' do
pod 'LoginComponent', :path => "../LoginComponent"
pod 'LoginComponent_Category', :path => "../LoginComponent_Category"
end
21. 终端进入Shopping主工程文件夹执行
$ pod install
接下来打开我们的主工程就会看到

22. 紧接着修改我们的主控制器

23. 最后运行模拟器跑起来,在首页点击view空白处会跳转到登录页

至此,iOS使用本地库进行组件化开发就已经结束了,这个组件化适合用在什么工程中呢
- 单人开发单项目,将功能组件化。
- 单人开发多项目,将公用的功能组件化。
- 多人开发单项目,将功能组件化。
- 多人开发多项目,将公用的功能组件化。
这里我要强调一下“多人开发多项目”,当多个人开发多个项目时会有两种情况:一个是多个人每个人都有权限去开发所有项目;第二个多个人开发多个项目,每个人只有权限去开发自己的项目,但是这几个项目中还是有公共的模块或者组件需要抽出来,这就不适合使用本地化的组件了,由此引出了“远程私有库 + 路由进行组件化开发”,我决定再写一篇文章去记录,两项内容写在一篇博客里面实在是太长了
iOS组件化开发之路(CTMediator),涉及到cocoapods本地库、远程私有库、远程公开库(二)