一、准备

  • 组件化

    • 随着业务需求的增长,在单工程 MVC 模式下,app 代码逐渐变得庞大,面对的高耦合的代码和复杂的功能模块,我们或许就需要进行重构了,以组件化的形式,将需要的组件以 pod 私有库的形式安装到最后的主工程中,组件间各自独立、解耦,仅依赖中间件进行通信,这或许就是极好的架构形式。

  • 使用 CocoaPods

  • 代码文件来源

二、制作基于 svn 的私有 sepc repo

  • 使用 svn 管理,先在 svn 服务器上新建一个放 spec 的远程仓库,本文以 SpecRepo 命名,该仓库不需要创建标准的 trunk、tags、branches 目录,仅仅是放组件的 spec 文件的。

  • 使用该 SpecRepo svn 地址建立私有 repo,命令行操作如下 pod repo-svn add SpecRepo http://10.211.55.3/svn/SpecRepo

    • 这里是 svn 管理的,利用的是 cocoapods-repo-svn 插件,如果是 git 管理的,那就是默认的 pod repo add xxx git地址

    • 建立了私有 SpecRepo,其本地.cocoapods/repos文件夹目录如下
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

    • 使用pod repo命令查看 repo 如下
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

三、基本的组件化的创建

  • 建立 CRProtocolManager 的组件私有库

    • cd 到 CRProtocolManager.podspec 所在目录,使用pod repo-svn push SpecRepo CRProtocolManager.podspec

    • 可在此之前进行 spec 文件有效性检查,pod repo-svn lint CRProtocolManager.podspec

    • 此时 svn 仓库和 .cocoapods/repo/SpecRepo 下都有 CRProtocolManager.podspec
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

    • 一个是 s.version 这个和 svn 要打 tag 的编号是一致,例如s.version = '1.0'

    • 一个是 s.source = {:svn =>'http://10.211.55.3/svn/CRProtocolManager', :tag => s.version.to_s },原来 s.source 是 git 地址,这里改为 svn 地址,指向 svn 代码仓库。

    • s.source_files、s.license、s.name(名字和svn仓库名、创建的组件名最好统一)可保持不变

    • s.summary、s.description、s.homepage、s.author 这些描述性的信息按需修改

    • s.ios.deployment_target = '8.0' 按需修改

      # 示例
      Pod::Spec.new do |s|
      s.name             = 'CRProtocolManager's.version          = '1.0's.summary          = 'CRProtocolManager.'s.description      = <<-DESCCRProtocolManager xxxx                DESCs.homepage         = 'http://www.baidu.com's.license          = { :type => 'MIT', :file => 'LICENSE' }
      s.author           = { 'HOWIE-CH' => 'zh200742zh@126.com' }
      s.source           = {:svn =>'http://10.211.55.3/svn/CRProtocolManager',  :tag => s.version.to_s }
      s.ios.deployment_target = '8.0's.source_files = 'CRProtocolManager/Classes/**/*' # s.resource_bundles = {
      #   'CRProtocolManager' => ['CRProtocolManager/Assets/*.png']
      # }
      # s.frameworks = 'UIKit', 'MapKit'# s.dependency 'AFNetworking', '~> 2.3'end
    • 该工程目录下 Podfile 文件中 pod 'CRProtocolManager', :path => '../' ,指向的外层文件夹下的 CRProtocolManager.podspec 文件,因此可以这样添加删除文件后使用pod install 来更新核心代码到工程里

    • 其中 Assets 文件夹下放与该组件有关的图片等资源文件
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

    • 使用该命令后最回答几个问题,分别是姓名、邮箱(用于 spec 文件中的作者信息)、选择语言(有 Swift 和 ObjC,这里选择 ObjC)、是否需要 demo 工程(这个是需要的,利用这个 demo 进行组件测试)、选择测试库(这里选 None)、do view based testing(这里选 No)

    • 使用 svn 管理,先在 svn 服务器上新建一个 CRProtocolManager 的仓库,因为是代码文件且需要使用 tag,所以使用标准的 trunk、tags、branches 目录

    • 使用 pod lib create CRProtocolManager 命令来下载带有默认模板的库,之后基于默认模板进行修改

    • 在 Finder 中,将 CRProtocolManager 的核心文件复制到 demo 工程中的 CRProtocolManager 下 Classes 文件夹下,并删除模板文件 ReplaceMe.m

    • 命令行中 cd Example 工程目录下,pod install 来更新工程的 CRProtocolManager 核心代码

    • 添加完核心代码后,更改 CRProtocolManager.podspec 文件

    • 将更改好的、测试好的组件提交到 svn CRProtocolManager 仓库 trunk 下,注意:因为模板是从 github.com 上 clone 的,所以这里先把 .git 文件夹删掉。(本文使用的是 smartSVN 管理工具)

    • 对代码进行打 tag,且编号为 1.0,与 spec 文件里的 s.version 一致。

    • 将 CRProtocolManager.podspec 文件提交到之前制作好的私有 sepc repo 中

  • 使用 CRProtocolManager 的私有库组件

    • pod install报错找不到组件,可使用pod repo remove SpecRepo后重新添加pod repo-svn add SpecRepo http://10.211.55.3/svn/SpecRepo,然后pod repo-svn update SpecRepo,若还没解决可能是 ruby、CocoaPods 版本不是最新的原因,建议重装后操作。

    • CRProtocolManager.podspec 文件提交到私有 sepc repo中后,pod search CRProtocolManager 搜索不到,可到/Users/HOWIE-CH/Library/Caches/CocoaPods下删除 search_index.json 文件后重试。

    • git 的话要同时标明私有 repo 地址和默认 repo 地址(以 source 'git地址' 形式)

    • xcode 新建一个工程,使用pod init创建 Podfile 文件

    • Podfile 中默认是搜索 .cocoapods/repo/master 对应的官方默认公用库的源,因此需要 Podfile 中添加本地 repo 源的地址

      platform :ios, '8.0'target 'test' doplugin 'cocoapods-repo-svn', :sources => [        'http://10.211.55.3/svn/SpecRepo' # 添加 svn 服务器中私有库 spec 的 repo
          ] 
      use_frameworks!
      pod 'CRProtocolManager'  # 本地 svn 私有库pod 'AFNetworking'    # 可直接 pod 公开第三方库end
    • 直接使用pod install 即可安装 CRProtocolManager 私有组件

    • 会出现的问题

四、私有库和私有库之间的依赖、私有库依赖共有库及 subspec 的应用

  • 其他组件和第三步一样进行操作,最后 svn 服务器截图和 SpecRepo 文件夹截图如下
    seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训
    seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

  • 依赖关系,例如对 CRGoodsDetail 进行探索 svn 的制作私有库之间的依赖的解决

    • 若出现问题则参考标题三中的解决方案

    • 该 demo 工程 Podfile 文件的 pod 'CRGoodsDetail' 指向上一个目录的 CRGoodsDetail.podspec 文件,因此会检测 s.dependency 依赖的库,依赖的私有库是在从 Podfile 中添加的私有 repo 的 svn 地址中去找的

    • CRGoodsDetail 中 CRGoodsDetailServiceProvide 依赖 CRGoodsDetailServiceProtocol 和 CRProtocolManager,CRGoodsDetailViewController 依赖 CRConfirmOrderServiceProtocol 和 CRProtocolManager。

    • pod lib create 创建好工程,进行核心的代码的拷贝和工程的更新操作之后,直接编译会报错的,因为存在依赖关系

    • 在 CRGoodsDetail.podspec 文件中添加

      # 需要的依赖私有库s.dependency 'CRProtocolManager's.dependency 'CRConfirmOrderServiceProtocol's.dependency 'CRGoodsDetailServiceProtocol'# 依赖公有库 ,可添加依赖的公有库s.dependency 'SDWebImage'
    • 在工程目录下的 Podfile 文件下添加私有 repo 的 svn 地址,才能下载私有库

      use_frameworks!
      target 'CRGoodsDetail_Example' do# 添加私有 repo 的 svn 地址plugin 'cocoapods-repo-svn', :sources => ['http://10.211.55.3/svn/SpecRepo']
      pod 'CRGoodsDetail', :path => '../'target 'CRGoodsDetail_Tests' doinherit! :search_pathsendend
    • pod install 就会装好依赖库,包括依赖的私有库和公有库

    • 该 demo 工程运行测试后没有报错后,要提交 svn,打(新) tag(组件的迭代开发维护),提交 spec 文件到私有 repo 中

  • subspec 的使用

    • 例如 CRGoodsDetail 中可分为模块文件(MVC 文件)及 Provider 文件,因此可使用 subspec

    • CRGoodsDetail 核心代码中分文件夹
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

    • CRGoodsDetail.podspec 文件中

      # subspec 及各自的依赖私有库
      s.subspec 'Module' do |m|m.source_files = 'CRGoodsDetail/Classes/Module/*'# 依赖私有库m.dependency 'CRConfirmOrderServiceProtocol'# 依赖公有库m.dependency 'SDWebImage'ends.subspec 'Provider' do |p|p.source_files = 'CRGoodsDetail/Classes/Provider/*'p.dependency 'CRGoodsDetailServiceProtocol'end# 公用的依赖私有库
      s.dependency 'CRProtocolManager'
    • 使用 subspec 后 pod search 效果
      seo优化培训,网络推广培训,网络营销培训,SEM培训,网络优化,在线营销培训

    • Podfile 中使用 subspec

      # pod 'CRGoodsDetail', :subspecs =>['Module'] #只加载本地 svn 私有库的某个 subspecpod 'CRGoodsDetail'   # 完整的 svn 私有库

五、图片资源、xib文件等

  • 创建的 demo 工程中,组件相关的图片是放到 Assets 文件下

  • spec 文件中需要添加
    s.resource_bundles = { 'CRGoodsDetail' => ['CRGoodsDetail/Assets/*'] }

  • 组件代码中加载图片不在是直接 imageName 了,图片打包的是一个 bundle 且 整个组件并不在 mainbundle 中,而是先要找到组件对应的 framework 包(可查看 Products 下,编译的 app 里的结构),然后找图片路径进行加载

  • 组件中的 xib

    • 使用 xib,以前的工程,xib 在 mainbundle 中。以组件形式的话,xib 在组件对应的 framework 包中

    • xib 中的图片路径,跟上面一样需要添加图片资源包的相对路径

六、其他

  • 使用 svn 的话,会提示输入用户名、密码,有时会因此报错,建议一开始就直接命令行 svn checkout xxx 一次,让电脑记住用户名、密码

  • 重构是一个细心的工作,尤其是组件的抽取、剥离,一般会分业务层、基础层、功能层等,业务层里有各个的业务功能模块,基础层里有常量、宏、工具类、分类等,功能层里是能够抽取出来的某些具体功能方法,相同层内的不同组件不产生依赖,业务层会依赖基础层和功能层,基础层和功能层之间不依赖,实际工作中还需要具体情况具体对待

  • 最后的主工程,需导入各个业务层里的组件,这里组件间的通信又是讨论的话题,url 、protocol、Target-Action等方案,自己也在学习和实践阶段,就不讨论,本文仅记录一些过程和问题。

http://www.cnblogs.com/howie-ch/p/7140678.html