美文网首页📚苹果
iOS组件化实战

iOS组件化实战

作者: xu_chen | 来源:发表于2019-07-15 11:46 被阅读0次

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

    一、简介

    定义

    简单来说,组件化就是将一个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

    相关文章

      网友评论

        本文标题:iOS组件化实战

        本文链接:https://www.haomeiwen.com/subject/mnggkctx.html