组件化实践

最近想了解一些组件化的知识,去看了Casa写的iOS应用架构谈 组件化方案这篇文章,Casa在文中针对蘑菇街的组件化方案提出了一些不一样的观点,陈述了本身的组件化方案。html

大神们讨论具体的实施方案,是对理论的描述,在架构层面来分析利弊,我看过以后感受仍是有点晦涩,具体的方案异同之处咱们先不说,今天咱们先从应用着手,在本身当前的工程实施组件化。ios

固然了,咱们选择使用的方案是Casa的CTMediatorgit

准备

首先咱们得先了解组件化这个概念,其实通俗的讲,就是把咱们的项目拆解成一个一个的小组件分别管理。咱们平时使用cocoapods继承的三方的库,能够理解成是一个公有的组件。咱们项目中,也能够把一些模块拆解出来,使用cocoapods来集成。这样拆解成一个个的组件的好处有不少,好比说业务模块之间解耦,复用模块,节省编译时间等等。github

因此咱们要先学会建立cocoapods私有库。json

这里多说一句,Casa的组件化方案在实施的时候,每独立出来一个组件,就会相应的建立一个Category工程,做为中间的调度,因此说,咱们每作一个组件,就要建立两个私有的pod工程。缓存

咱们结合Casa这篇在现有工程中实施基于CTMediator的组件化方案,来作一下补充或者说是注解吧,本文中的流程取自于上文。架构

建立私有Pod工程

1. 先去开一个repo,这个repo就是咱们私有Pod源仓库
2. pod repo add [私有Pod源仓库名字] [私有Pod源的repo地址]
3. 创立一个文件夹,例如Project。把咱们的主工程文件夹放到Project下:~/Project/MainProject
4. 在~/Project下clone快速配置私有源的脚本repo:git clone git@github.com:casatwy/ConfigPrivatePod.git
5. 将ConfigPrivatePod的template文件夹下Podfile中source 'https://github.com/ModulizationDemo/PrivatePods.git'改为第一步里面你本身的私有Pod源仓库的repo地址
6. 将ConfigPrivatePod的template文件夹下upload.sh中PrivatePods改为第二步里面你本身的私有Pod源仓库的名字

首先咱们先建立一个名为Project的文件,而后把咱们项目的主程序,咱们叫作MainProject放到Project路径下,而后在Project路径下clone出咱们须要的脚本(Casa提供)组件化

在~/Project下clone快速配置私有源的脚本:
git clone git@github.com:casatwy/ConfigPrivatePod.git

如今咱们的文件目录结构是这样的。this

Project
├── ConfigPrivatePod(脚本文件)
└── MainProject

在Project路径下建立咱们的组件工程(一个普通的iOS工程),咱们把这个工程名字叫PayComponents (模拟抽取项目中的支付模块)。spa

当前目录结构

Project
├── ConfigPrivatePod
├── MainProject
└── PayComponents

有了本地的工程以后,咱们如今须要建立一个repo,做为咱们的私有pod源仓库。也就是在github,或者gitee(码云)上面建立一个项目,放咱们的项目代码,命名PayComponents。

而后呢,咱们还须要建立一个东西,就是私有Pod源仓库名字。

pod repo add [私有Pod源仓库名字] [私有Pod源的repo地址]

落实到咱们这个项目中,咱们应该这样写。

pod repo add PayComponents https://gitee.com/LittleBin/PayComponents.git

那这到底表明着咱们建立了什么?

咱们打开finder->前往->前往文件夹,而后输入~/.cocoapods/repos

能够看到目录是这样子的

1.png

repos路径下面有一个master,一个payComponents。这两个文件夹咱们能够粗略的认为他和pod search还有install有关。

打个比方就拿search来讲,咱们查询一个库的时候会用下面这个命令

pod search AFNetworking

而后会从master路径下找到AFNetworking,而后列出来他有哪些版本什么的。咱们有的时候会发现一个库其实已经跟新到2.x.x版本,可是咱们search出来只有1.x.x,这也多是咱们的cocoapods没有更新,咱们的master路径下没有新的版本。

这个PayComponents文件夹,就表明咱们本地有一个私有的pod库。咱们search的时候,也会查这些本地的私有库。

下面把远程的这个repo和咱们本地建立的项目关联到一块儿,这个工做Casa给咱们提供的脚本就能够完成,顺便还会帮咱们生成.podspec的文件,具体这个文件的做用咱们后面再说,还会初始化podfile。

咱们进到ConfigPrivatePod文件中,执行config.sh脚本,而后在终端根据提示输入就好了。

[localhost:ConfigPrivatePod sunxiaobin$ ./config.sh 


Enter Project Name: PayComponents
Enter HTTPS Repo URL: https://gitee.com/LittleBin/PayComponents.git
Enter SSH Repo URL: git@gitee.com:LittleBin/PayComponents.git
Enter Home Page URL: https://gitee.com/LittleBin/PayComponents

================================================
  Project Name  :  PayComponents
  HTTPS Repo    :  https://gitee.com/LittleBin/PayComponents.git
  SSH Repo      :  git@gitee.com:LittleBin/PayComponents.git
  Home Page URL :  https://gitee.com/LittleBin/PayComponents
================================================

confirm? (y/n):y
copy to ../PayComponents/FILE_LICENSE
copy to ../PayComponents/.gitignore
copy to ../PayComponents/PayComponents.podspec
copy to ../PayComponents/readme.md
copy to ../PayComponents/upload.sh
copy to ../PayComponents/Podfile
editing...
edit finished
cleaning...
Initialized empty Git repository in /Users/fmb/Documents/LEARN/Project_test/PayComponents/.git/
clean finished
finished
localhost:ConfigPrivatePod sunxiaobin$

Enter Project Name:的时候,后面的名字必定要跟咱们建立的PayComponents工程同样,要否则脚本找不到文件,就配置不了。

脚本跑完以后PayComponents里面变成下面这样子。

2.png

咱们要修改一下Podfile文件和upload.sh。下面是生成的Podfile文件里面的内容

# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'

source 'https://github.com/ModulizationDemo/PrivatePods.git'
source 'https://github.com/CocoaPods/Specs.git'

use_frameworks!

target 'PayComponents' do
 
end

由于脚本都是照着模板来生成的这些文件,上面是podfile文件里面的内容,咱们要把第一个source后面的'https://github.com/ModulizationDemo/PrivatePods.git'改为咱们这个库的地址,https://gitee.com/LittleBin/PayComponents.git

而后在upload.sh中,最后一行

pod repo push PrivatePods PayComponents.podspec --verbose --allow-warnings --use-libraries --use-modular-headers

把PrivatePods替换为咱们上面的私有pod库名称。
也就是咱们以前执行的下面这个命令中的PayComponents。

//不用重复执行
pod repo add PayComponents https://gitee.com/LittleBin/PayComponents.git

咱们在看一下PayComponents项目文件的结构,脚本给咱们生成了一个空的PayComponents文件。

3.png

咱们须要把这个文件拖拽到咱们的项目中

4.png

而后咱们这个PayComponents组件的文件就所有放到这个路径下。咱们的私有库暂时就先写到这里。下面建立咱们的Category工程

建立Category工程

由于篇幅缘由,这里我把建立Category工程略过一下,不一一展现了。

其实按道理说在实际项目中,这个Category工程也要作成私有库的,就像咱们上面说的步骤,先建立本地工程,建立远程的repo,而后建立本地私有库(pod repo add ...),在用脚本关联本地和远程的库,而后修改Podfile和upload.sh等等这一整套步骤。

最终Category项目的结构是下面这样的。(包含为CTMediator添加的分类)

5.png

咱们调用PayComponents组件里面的vc都是经过这个category来调用的。因此说咱们的这个Pay_category工程应该在Podfile文件中加上pod 'CTMediator',而后执行pod install

咱们以前有遇到过这种状况,咱们在使用A库的时候,pod install以后,会自动帮咱们导入A库依赖的B库,回到咱们的项目也就是说当咱们在主工程里面集成Pay_Category这一组件的时候,应该默认帮咱们把CTMediator库和PayComponents组件也集成进工程。这就要修改Pay_Category.podspec文件。

在文件的最底部,end以前加上下面两句

s.dependency "CTMediator"
s.dependency "PayComponents"

说回咱们新建的这个CTMediator+pay文件,咱们要在主工程MainProject跳转到PayComponents里面的VC,因此CTMediator+pay应该提供一个返回vc的方法,以下:

- (UIViewController *)PayViewController {
  
    return [self performTarget:@"PayManager" action:@"pay" params:nil shouldCacheTarget:NO];
}

咱们想不去管return后面的代码是什么意思,只要他是返回了vc给咱们就能够。

而后在MainProject里面的跳转代码就以下:

// 导入CTMediator+pay头文件
UIViewController * viewController = [[CTMediator sharedInstance] PayViewController];
[self.navigationController pushViewController:viewController animated:YES];

下面咱们再来讲return [self performTarget:@"PayManager" action:@"pay" params:nil shouldCacheTarget:NO];是什么意思。

咱们能够从CTMediator的源码中,看一下- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget这个方法。

那这里我就不绕圈子里,直接说结论,其实在上述的方法中是找到了一个叫Target_PayManager的类,调用了它里面的Action_pay方法,这个前缀Target_和Action_是在方法内部拼接的,因此说咱们能够得出,CTMediator是经过反射拿到类名和方法名,而后调用,获得目标vc的。因此说在PayComponents工程中,咱们还得建立Taregt文件来作间接的调用。

6.png

这里的Target_PayManager文件的文件名后半部分PayManager要跟- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget里面的targetName对应起来,而后类里面的方法名字也得对应。(PayViewController就是咱们的目标文件)

- (UIViewController *)Action_pay:(NSDictionary *)param {
    
    PayViewController *viewController = [[PayViewController alloc] init];
    viewController.param = param;
    return viewController;

}

最后咱们在MainProject的Podfile文件中引入Pay_Category库就好了。这个时候咱们的私有库可能尚未彻底建立成,因此咱们能够用这种导入本地的方法

pod "Pay_Category", :path => "../Pay_Category"

固然若是私有库作好了,就只须要pod "Pay_Category"就好了。

完善私有库

在Casa的博客中说到,可使用他的upload.sh脚原本更新私有库代码,我用过它的脚本,老是有错无,并且库的版本号也是依次+1的形式,版本号我喜欢x.x.x这种,因此我选择本身提交代码,更新私有库。

针对于每一个工程来讲,首先是一些基本的提交代码操做,

git add .
git commit -m “新版本号“
git tag 新版本号
git push origin master —tags

要更新私有库,咱们拿PayComponents这个项目来讲,执行下面的指令

//私有库升级
pod repo push PayComponents  PayComponents.podspec

这个PayComponents就是咱们pod repo add时候起得名字,后面是.podspec文件,这操做等于把咱们的私有库更新推到咱们本地的库里面。注意.podspec里面的版本号要记得更新,与tag一致。

那这种私有库咱们项目的其余成员,仍是拿PayComponents这个来讲,首先在代码管理库上面得给他们下载代码的权限,而后执行下面:

//待核实~ 
pod repo add PayComponents https://gitee.com/LittleBin/PayComponents.git

公有库

补充一点,那若是想作成公有库,让你们均可以使用要怎么搞?
执行下面操做:

pod trunk push PayComponents.podspec

就能够把组件推到Cocoapods主仓库。别人就能够经过pod search来查找你的库了。

pod trunk push 可能失败,由于首次使用trunk须要注册本身的电脑。

pod trunk register [E-mail] [User Name]

执行完成以后,会受到一封验证邮件,按邮件提示完成验证便可。

所有都完成了以后pod search也可能会搜不到本身的库,这时候能够尝试把缓存删掉

使用命令:rm ~/Library/Caches/CocoaPods/search_index.json

清除后,再从新搜索,此时CocoaPod会从新建立搜索索引。

这只是一些可能的缘由,具体的问题须要具体针对解决。


参考文章

https://casatwy.com/modulizat...

https://www.jianshu.com/p/59c...

https://www.jianshu.com/p/757...

https://www.jianshu.com/p/1d8...

相关文章
相关标签/搜索