一、准备
组件化
随着业务需求的增长,在单工程 MVC 模式下,app 代码逐渐变得庞大,面对的高耦合的代码和复杂的功能模块,我们或许就需要进行重构了,以组件化的形式,将需要的组件以 pod 私有库的形式安装到最后的主工程中,组件间各自独立、解耦,仅依赖中间件进行通信,这或许就是极好的架构形式。
使用 CocoaPods
如果你的 Mac 系统升级过了,避免出现莫名的问题,强烈建议重装 CocoaPods 及更新 ruby。(可参考 http://www.jianshu.com/p/8169f5d7f364)
CocoaPods 下载框架的原理及 spec、Podfile 文件,可参考 http://www.jianshu.com/p/8a7b9232cbab或 http://blog.csdn.net/morenyaojing/article/details/53376475 。
CocoaPods 默认的 spec repo,是基于 git 的,可创建基于 git 管理的私有库 spec repo,因公司性质及要求,代码一律使用内部 svn 管理。因此本文完全使用 svn,来进行私有库制作。(使用 git 的文章网上很多,更方便,其实最终感觉也都差不多)
安装 cocoapods-repo-svn 插件,参考 https://github.com/dustywusty/cocoapods-repo-svn 。
代码文件来源
因公司项目原因,本文以网上的 demo 代码来演示。demo 来源 https://github.com/sun6boys/CRMainProject
二、制作基于 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
文件夹目录如下使用
pod repo
命令查看 repo 如下
三、基本的组件化的创建
建立 CRProtocolManager 的组件私有库
cd 到 CRProtocolManager.podspec 所在目录,使用
pod repo-svn push SpecRepo CRProtocolManager.podspec
可在此之前进行 spec 文件有效性检查,
pod repo-svn lint CRProtocolManager.podspec
此时 svn 仓库和 .cocoapods/repo/SpecRepo 下都有 CRProtocolManager.podspec
一个是 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 文件夹下放与该组件有关的图片等资源文件
使用该命令后最回答几个问题,分别是姓名、邮箱(用于 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 文件夹截图如下
依赖关系,例如对 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 核心代码中分文件夹
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 效果
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