最近想了解一些组件化的知识,去看了Casa写的iOS应用架构谈 组件化方案这篇文章,Casa在文中针对蘑菇街的组件化方案提出了一些不一样的观点,陈述了本身的组件化方案。html
大神们讨论具体的实施方案,是对理论的描述,在架构层面来分析利弊,我看过以后感受仍是有点晦涩,具体的方案异同之处咱们先不说,今天咱们先从应用着手,在本身当前的工程实施组件化。ios
固然了,咱们选择使用的方案是Casa的CTMediator。git
首先咱们得先了解组件化这个概念,其实通俗的讲,就是把咱们的项目拆解成一个一个的小组件分别管理。咱们平时使用cocoapods继承的三方的库,能够理解成是一个公有的组件。咱们项目中,也能够把一些模块拆解出来,使用cocoapods来集成。这样拆解成一个个的组件的好处有不少,好比说业务模块之间解耦,复用模块,节省编译时间等等。github
因此咱们要先学会建立cocoapods私有库。json
这里多说一句,Casa的组件化方案在实施的时候,每独立出来一个组件,就会相应的建立一个Category工程,做为中间的调度,因此说,咱们每作一个组件,就要建立两个私有的pod工程。缓存
咱们结合Casa这篇在现有工程中实施基于CTMediator的组件化方案,来作一下补充或者说是注解吧,本文中的流程取自于上文。架构
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
能够看到目录是这样子的
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里面变成下面这样子。
咱们要修改一下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文件。
咱们须要把这个文件拖拽到咱们的项目中
而后咱们这个PayComponents组件的文件就所有放到这个路径下。咱们的私有库暂时就先写到这里。下面建立咱们的Category工程
由于篇幅缘由,这里我把建立Category工程略过一下,不一一展现了。
其实按道理说在实际项目中,这个Category工程也要作成私有库的,就像咱们上面说的步骤,先建立本地工程,建立远程的repo,而后建立本地私有库(pod repo add ...),在用脚本关联本地和远程的库,而后修改Podfile和upload.sh等等这一整套步骤。
最终Category项目的结构是下面这样的。(包含为CTMediator添加的分类)
咱们调用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文件来作间接的调用。
这里的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...