iOS组件化实战


最近在研究组件化,发现网上的资料有很多,很详细,可是看的越多感觉越懵😳,我现在需要的是尽量简单化,于是就有了这一篇实战贴,简单实用!

一、简介

定义

简单来说,组件化就是将一个APP中的代码进行抽取,分成若干个项目,然后按照cocoapods的方式进行组织,形成一个拥有完整业务逻辑的工程。也就是说一个组件就是一个可以独立运行的项目。它就是用来解耦的,当你的APP业务越来越庞大的时候,就需要将业务隔离独立开发

优缺点

优点

  • 组件的独立性,各组件独立开发,互不影响,可以减少提交代码时的冲突
  • 资源重用,将于业务无关的代码抽离出来放在一个基础组件中
  • 高效迭代
  • 配合二进制,可以加快项目的编译速度

缺点

  • 开发起来步骤要复杂些,代码的抽离也不是很容易

二、组件的划分

每一个组件都是一个独立的pod库,我们把组件化的代码放在Git上托管,制作成私有pod,然后通过cocoapods就可以连接各个组件,最后把它们合在一起,变成一个完整的项目

原则

  1. 基础代码;基础配置(宏定义、常量)、分类、网络请求、其它的一些工具类
  2. 功能代码;自定义的一些UI控件;一些功能类,如音频处理、断点续传等
  3. 业务代码;具体的业务,如首页模块、个人中心模块等

三、组件的创建

pod 的原理

当我们执行 pod install 把代码集到项目中,这个过程会发生一些什么事情?
AFNetworking为例,当它的源码提交到Git上的时候,里面会有一个.spec的文件,这个文件是描述框架信息的,比如框架的名称、版本号、真实源码地址等。
Git上有专门的一个远程仓库用来存放所有的 .spec 文件,我们执行pod install的时候,会先去本地找这个库对应的.spec文件,这个文件是当你在安装pod执行pod setup的时候或者更新pod的时候,就会把远程仓库里的.spec文件拉取到本地。那如果本地找不到这个描述文件,那么它就会去把远程仓库的spec文件拉取到本地,然后再去找,找到了之后,就能够得到描述文件里的真实源码地址,通过Git把它拉取下来

制作一个私有pod库(重难点)

步骤

首先,打开终端,进入项目主目录中

cd ~ 
cd desktop
mkdir 组件化项目
cd 组件化项目
1. 组件工程(用来发布的组件,开发时用的工程)
  • 思路:新建一个空白工程,在工程中进行业务代码的开发,比如首页;开发完毕后将代码提交到Git
  • 具体步骤
  • 码云上新建一个私有仓库(为了代码安全,搞成私有的!)
  • clone 到本地,进行业务代码的开发(所有的代码都放在一个主目录文件夹中如 ExamComponent),可多人开发,使用 Git 做版本控制
  • 开发完毕后,上到到Git上,把ExamComponent文件夹拷贝出来
2. 私有pod库
  • 创建本地pod库

    • 进入项目目录中,执行以下命令

      cd 组件化项目   
      pod lib create CXComponentBasic
      

      这个是pod提供的一个模板命令,可以创建一个标准的pod库,我们只需要把拷贝过来的业务代码放在 Classes 文件夹中,然后修改.spec文件,就可以发布了,稍候将详细介绍

  • 创建私有索引库
    通过上面介绍的pod的原理,我们知道每个开源库都对应一个.spec文件,这个.spec文件默认是放在开源的pod索引库里的,别人都可以搜索到,我们如果需要创建私有pod库,就不能把.spec文件放在默认开源索引库里,我们需要把它放在自己的私有索引库中。

  1. 码云上新建一个私有库,用来存放spec文件,这个库也可称为索引库
  2. 回到终端,将这个索引库关联到本地,命令如下
pod repo add CXGiteePrivateRepo https://git.oschina.net/baiyingqiu/CXGiteePrivateRepo.git

CXGiteePrivateRepo 是私有索引库的名称
可通过命令pod repo可查看本地有哪些索引库

  • 关联pod库的远程仓库
    前面两步已经把本地pod库私有索引库创建好了,下面就不要把pod库的.spec文件,上传到私有索引库中就行了。

  • 关联本地pod库

    • 码云上新建一个私有库,名称和本地pod库一样,用来和它进行关联,命令如下
    git remote add origin https://gitee.com/sunnoryChen/CXComponentBasic.git
    
  • 修改.spec文件
    修改版本号和路径等

  • 发布

    • 打开本地私有pod库的示例项目
    cd xx  
    pod install
    clean
    

    先执行下安装,看看pod库是否报错,如果报错说明你的业务代码有问题,得改!

    • 返回上一级目录
      确保你的业务代码正常后,就可以返回到上级目录,准备发布啦

      • 关联远程仓库
      git remote add origin https://gitee.com/sunnoryChen/CXComponentBasic.git
      

      git remote -v 可查看关联了哪些远程仓库

      • 上传到远程仓库
      git add .
      git commit -m “0.1.2”
      git tag 0.1.2
      git push origin master --tags -f 
      

      注意 tag 值需要和pod的版本号保持一致

      • 验证.spec文件是否可用
         pod spec lint --sources='https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git,https://github.com/CocoaPods/Specs' --allow-warnings
      

      这两个路径一个是我们的私有索引库地址,一个是pod的公共索引库地址

      • 发布到私有索引库中
        验证通过后,验证不通过,那就看哪报错就改哪儿吧,反正有不少坑的😆
        发布的命令如下:
      pod repo push CXGiteePrivateRepo CXComponentBasic.podspec --sources='https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git,https://github.com/CocoaPods/Specs' --allow-warnings
      

      CXGiteePrivateRepo 是我们之前创建的本地索引库名
      CXComponentBasic.podspec 就是我们要发布库的索引库

3. 组件的使用

修改 podfile 文件,如下

# 使用私人pod库的需要在Podflie中添加这句话,指明你的版本库地址
source 'https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git'
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, ‘8.0’

pod 'CXComponentBasic', '~> 0.1.2'

Tips

  1. 组件项目中怎么使用 .pch 预编译文件

找到pod的目录 “Support Files - RDZJComponentLogin-prefix.pch” ,这个相当于实际项目中的pch文件,防止一些预编译的命令,可全局调用的

  1. 组件内怎么分层级的

修改 .spec文件

#头文件
s.public_header_files = 'Pod/Classes/Category/UIKit/CXUIKit.h'

s.subspec 'Category' do |vdr|
    vdr.subspec 'Foundation' do |vd|
    vd.source_files = "CXComponentPublic/Classes/Category/Foundation/**/*"
    end
  vdr.subspec 'UIKit' do |vd|
    vd.source_files = "CXComponentPublic/Classes/Category/UIKit/**/*"
   end
end
  1. 组件怎么依赖三方库

    s.dependency 'MBProgressHUD', '~> 1.0.0'

  2. 组件怎么使用自己活三方的 framework 或者 .a 文件

    s.ios.vendored_frameworks = "xxx//.framework"
    s.ios.vendored_libraries = "xxx/
    /.a”

  3. 组件内部相互依赖?

s.subspec 'BaseClass' do |bsc|
bsc.source_files = "TestPod/Classes/BaseClass/*"
# 字库BaseClass中用到了字库Controls中的东西,需要添加依赖
bsc.dependency "TestPod/Controls"
end

TestPod 是你的组件名,这个命令的意思是 TestPod 组件里的 BaseClass 子库依赖了 的 TestPod 组件中的 Controls子库

  1. 组件中怎么使用资源文件比如图片Xibtxt文档,因为组件中图片不是放在默认 Main Bundle中的,所以是不能使用ImageNamed 方法获取图片的,需要知道当前图片所在的 Bundle , 例如

图片

+ (instancetype)cx_imagePathWithName:(NSString *)imageName bundle:(NSString *)bundle targetClass:(Class)targetClass {
        NSInteger scale = [[UIScreen mainScreen] scale];
        NSBundle *currentBundle = [NSBundle bundleForClass:targetClass];
        NSString *name = [NSString stringWithFormat:@"%@@%zdx",imageName,scale];
        NSString *dir = [NSString stringWithFormat:@"%@.bundle",bundle];
        NSString *path = [currentBundle pathForResource:name ofType:@"png" inDirectory:dir];
        return path ? [UIImage imageWithContentsOfFile:path] : nil;
}

Xib

+ (instancetype)base_mainView {
    NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];
    CXBaseXibView *view = (CXBaseXibView *)[currentBundle loadNibNamed:@"CXBaseXibView" owner:nil options:nil].lastObject;
    view.frame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 128);
    return view;
}

txt

NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];
NSLog(@"text_currentBundle = %@",currentBundle);
NSString *dir = [NSString stringWithFormat:@"%@.bundle",@"RDZJComponentLogin"];
NSString *plistPath = [currentBundle pathForResource:@"userDeal" ofType:@"txt" inDirectory:dir];
NSLog(@"plistPath = %@",plistPath);

Questions

  1. pod发布命令不可用
    需要先注册一下pod 才能有发布库的权限 eg.

pod trunk register 2235037295@qq.com "georry"

  1. 发布库时,报 Swift 版本错误

在 podspec中添加 s.swift_version = '4.0'

  1. 更新私有库版本时,出现
    [!] The repo MySpecs at ../../../../.cocoapods/repos/MySpecs is not clean
    需要更新一下我们的索引库
    执行命令pod repo update 本地私有索引库名称(MySpecs)

执行命令 pod repo update 本地私有索引库名称(MySpecs)

  1. 在组件内部使用三方库时,要这样导入 Masonry/Masonry.h
  2. OC、Swift 混编包,怎么做组件

不使用!!!

四、组件的通讯

采用 CTmediator 的路由解决方案,将需要暴露的接口放在它的分类方法中,具体使用方法可参考上篇文章

参考资料

1
2
3

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容