iOS组件化之私有库

  • 随着公司业务的不断发展,应用的代码体积将会愈来愈大,业务代码耦合也愈来愈多,代码量也是急剧增长
  • 若是仅仅完成代码拆分还不足以解决业务之间的代码耦合,而组件化是一种可以解决代码耦合、业务工程可以独立运行的技术
  • 这篇文章主要介绍远程私有库的建立和管理以及本地索引库的使用, 而且可参照发布开源框架到CocoaPods入坑指南
  • 我的原文博客地址: iOS组件化之私有库

本地库方案

建立本地私有库

  • 首先须要一个宿主工程MainMoudle和一个用于存放全部本地私有库的文件夹AllMoudles, 这两个文件夹在同一目录下
  • AllMoudles文件夹中建立一个私有库TitanFMBase, 在子目录建立Classes用于存放全部的文件, 目录以下: AllMoudles/TitanFMBase/Classes
  • Classes文件夹中添加文件, 并提交到本地git
//进入TitanFMBase文件夹
cd xxx/AllMoudles/TitanFMBase

//初始化git
git init

//将本地代码提交到本地仓库
git add .

// 提交修改到本地仓库
git commit -m '你的修改记录'

//建立spec文件
pod spec cteate TitanFMBase
复制代码

最后打开TitanFMBase文件夹中的TitanFMBase.podspec, 修改对应的配置信息, 可参考修改博客html

注意点ios

source配置中, 本地库的git地址不须要填git

s.source = { :git => "", :tag => "#{s.version}" }
复制代码

使用本地私有库

  • 安装和使用本地私有库和和远程私有库步骤同样, 不一样的是:
    • 远程私有库不须要指明库的地址
    • 本地私有库须要制定库地址(相对路径便可)
  • 使用path的形式添加框架依赖
pod 'TitanFMBase', :path => '../AllMoudles/TitanFMBase'
复制代码

注意点github

  • 入伙时本地私有库, 不须要使用pod lib lint或者pod spec lint验证spec文件的正确性
  • 由于有些字段只有远程私有库才须要设置, 只要保证本地私有库的路径正确, 并不影响使用

远程私有库

  • 当咱们在终端执行pod search命令时, 搜索的实际上是本地缓存的spec文件, 固然第一次使用时须要先更新本地的spec文件
  • 可在终端执行pod repo命令查看当前本地的索引库, 或者查看目录~/.cocoapods/repos/master/Specs
  • 在组件化开发过程当中, 为防止代码泄露, 咱们必需要建立本身的本地索引库
  • 发布开源框架到CocoaPods入坑指南文章中提到了一种建立方式
    • 可是上述提到的建立方式, 须要手动建立podspec文件
    • 须要手动进行git管理, 不能测试, 须要手动添加测试工程
  • 执行pod repo add TitanSpec http://xxxx命令, 可建立一个新的本地索引库
  • 建立远程索引库, 码市
  • 除图中红色箭头外, 其余地方不须要填写, 新建便可

CreateSpec

建立远程私有库

  • pod lib create xxx
  • 规范建立私有库, 执行上述命令, 可同时建立spec文件和测试工程等
  • 根据提示建立不一样的配置文件便可, 建立完成后, 将须要添加的私有库文件放到xxx/xxx/Classes文件夹下便可, 默认建立的.m文件可删除
  • 最后须要打开Example目录下的测试工程, 并执行pod install命令, 将你的私有库文件安装到测试工程
  • 最后修改xxx文件下的xxx.podspec文件中相关配置便可

createLib

作完上述工做便可将项目全部文件提交到远程私有库了缓存

// 将本地代码加入本地仓库里
git add .

// 提交修改到本地仓库
git commit -m '你的修改记录'

// 查看当前的远程链接
git remote
// 添加名称为origin的远程链接
git remote add origin '你的github项目地址'

// 在push以前, 查看spec是否配置有问题
// 验证本地spec文件是否有误
pod lib lint
// 验证远程spec文件是否有误
pod spec lint

// 推送master分支的代码到名称为origin的远程仓库
git push origin master
复制代码
  • 正常状况下本地验证通常没问题, 远程验证正常状况下会有问题
  • 本地验证不会验证s.source后面的tag
  • 远程验证会验证tag, 而至此咱们的tag尚未设置, 因此验证不会经过, 须要打标签
  • 设置好tag, 再次验证应该就是没问题的了
// 查看当前的tag值
git tag

// 设置tag值
git tag "0.0.1"  

// 上传提交tag
git push --tags


// 删除标签相关命令
// 先删除本地再删除远程标签, 删除后须要从新打标签
// 删除本地标签
git tag -d 0.0.1

// 删除远程标签
git push origin :0.0.1

复制代码

提交私有的SpecRepo

向私有的SpecRepo中提交podspec:bash

pod repo push SpecName XXX.podspec
复制代码

注意点微信

  • 提交podspec的过程当中会有验证, 最好在提交以前先验证spec文件的配置是有问题pod lib lint
    • 警告可使用--allow-warings忽略
    • 可是涉及到的错误信息必定要解决
  • 提交过程当中, 会提交信息到远程私有索引库

使用私有库

  • 检索私有库: pod search XXX
    • 若是检索不到, 能够先到私有索引库内, 看看是否存在私有库
    • 若是存在仍是检索不到, 则直接删除私有库索引文件, 从新配置
  • Podfile文件中, 同事使用私有库和第三方库是须要指定对应的source
  • pod repo命令执行后的结果
master
- Type: git (master)
- URL:  'https://github.com/CocoaPods/Specs.git'
- Path: /Users/xxx/.cocoapods/repos/master

TitanFMSpec
- Type: git (master)
- URL:  'https://git.coding.net/CoderTitan/TitanFMSpec.git'
- Path: /Users/xxx/.cocoapods/repos/TitanFMSpec
复制代码

Podfile文件中配置信息app

// 远程私有库
source 'https://git.coding.net/CoderTitan/TitanFMSpec.git'
// 官方仓库
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '8.0'

target 'TitanjunFM' do
  use_frameworks!

pod 'TitanFMBase'
pod 'MJExtension'

end
复制代码

更新私有库

更新远程私有库

  1. 修改xxx/xxx/Classes文件夹下对应的库文件
  2. 更新测试工程的Pod库文件: pod update --no-repo-update
  3. 更新xxx.podspec文件的配置信息, 版本号必定要改
  4. 提交代码到远程仓库: git push origin master
  5. 更新tag标签: git push --tags
  6. 更新远程和本地的私有索引库: pod repo push SpecName XXX.podspec

私有库依赖

初步设计方案

  • 在设计私有库的过程当中不免可能会涉及到使用其余第三方库的状况, 又该如何解决这种问题
  • 添加组件依赖: 在podspec文件配置中, 添加以下依赖代码
s.dependency 'AFNetworking'
s.dependency 'SDWebImage'
复制代码
  • 注意依赖, 以及框架头文件中, 不要直接导入依赖框架的头文件
  • 也就是说, 上述涉及到的所依赖的第三方库, 在项目的Podfile文件中, 不会再导入该类库

优化方案

上述方案存在的问题: 假如另一个业务线, 仅仅须要依赖一些基础配置, 可是, 若是把整个库做为依赖, 便会导入一些不用的冗余代码框架

  • 这样, 咱们如今终端执行pod search AFNetworking, 看一下AFNetworking的搜索结果
  • 会看到Subspecs中, 将AFNetworking分红了几个不一样的部分, 这样咱们就能够根据不一样的功能需求导入不一样部分的代码便可, 防止代码冗余
-> AFNetworking (3.2.1)
   A delightful iOS and OS X networking framework.
   pod 'AFNetworking', '~> 3.2.1'
   - Homepage: https://github.com/AFNetworking/AFNetworking
   - Source:   https://github.com/AFNetworking/AFNetworking.git
   - Versions: 3.2.1, ......,0.5.1 [master repo]
   - Subspecs:
     - AFNetworking/Serialization (3.2.1)
     - AFNetworking/Security (3.2.1)
     - AFNetworking/Reachability (3.2.1)
     - AFNetworking/NSURLSession (3.2.1)
     - AFNetworking/UIKit (3.2.1)
复制代码

为解决将私有库中的代码分红不一样的功能模块, 使用subspec语法配置podspec文件, 以下:组件化

//格式:
s.subspec 'XXX' do |x|
    //须要导入的全部文件的相对路径
    x.source_files = '相对路径/**/*'
    //须要导入的.h头文件的相对路径
    x.public_header_files = '相对路径/**/*.h'
    //须要导入的资源文件的相对路径
    x.resource = "相对路径/**/*.{bundle,nib,xib}"
    //所依赖的其余的库
    x.dependency 'AFNetworking', '~> 1.0.0'
end

//示例:
s.subspec 'Network' do |n|
    n.source_files = 'TitanFMBase/Classes/Network/**/*'
    n.dependency 'AFNetworking'
end
复制代码
  • 将原来的s.source_files改为上述语法便可
  • 外部使用时只需导入pod 'AFNetworking/Reachability'便可

私有库的资源引用

xib&storyboard

  • 全部私有库中的xib必须动态获取
  • 私有库中引用图片资源或者Xib资源时, 又该如何引用呢?
  • 都知道项目中引用Xib时, 一般方式是[[NSBundle mainBundle] load]方式, 可是这种方式在私有库中显然不适用
  • 在私有库中加载私有库中的XIb, 使用方法[NSBundle bundleForClass:self]动态获取, 具体看一下
// MiddleView.m
    
NSBundle *mainBundle = [NSBundle mainBundle];
NSBundle *bundle = [NSBundle bundleForClass:self];
    
MiddleView *middleView = [[bundle loadNibNamed:@"MiddleView" owner:nil options:nil] firstObject];

// 打印一下上述两个bundle以下:
// mainBundle:
NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Application/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app>
// bundle:
NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Application/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app/Frameworks/TitanFMMain.framework>
复制代码
  • 从上述信息中能够看到, 项目中正常的Xib等资源文件是放在TitanFM.app中的
  • 而私有库的Xib等资源文件是放在TitanFM.app/Frameworks/TitanFMMain.framework文件目录下的, 因此私有库中的资源文件加载, 要到对应的文件目录下
  • 具体也能够到TitanFM.app中查看, 找到对应的app文件, 显示包内容, 便可层级查看

图片资源

图片存放问题

  • 正常项目中, 咱们的图片通常都会放在相似后缀.xcassets的文件中
  • 在设计私有库时, 在Classes的同级目录中会默认建立一个Assets的文件夹, 用于存放图片等资源
  • podspec文件中, 一样修改加载文件资源的配置, 以下:
s.resource_bundles = {
   'MainMoudle' => ['MainMoudle/Assets/*']
}
复制代码

修改完配置信息和图片记得执行pod install把资源文件导入到项目中

私有库图片的使用

xib中加载图片, 须要在图片前面加上组件的主bundle, 相似: MainMoudle.bundle/tabbat_back

xibimage

私有库中使用代码加载图片, 必定不能使用imageNamed方法

//1. 获取当前的bundleName
NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];

//2. 根据图片名称, 在bundle中检索图片路径
NSString *path = [currentBundle pathForResource:@"tabbar_np_play@2x.png" ofType:nil inDirectory:@"MainMoudle.bundle"];

//获取图片
UIImage *image = [UIImage imageWithContentsOfFile:path];
复制代码

引用图片须要注意的的是

  • 图片引用过程当中不会自动选择@2x和@3x的图片, 因此必须手动指定具体的图片名称包括图片后缀名
  • 获取路径的方法pathForResource, 也要必须指明图片所在的bundle路径, 即inDirectory参数不可为空

提交本地的私有库索引

  • 当你的私有库中引用了其余的私有库框架, 好比MainMoudle中引用了TitanFMBase/Category部分
  • 则切记不要进行本地和远程的spec验证, 不然可能回报错, 缘由只是由于spec中默认的依赖库是共有的索引库, 私有库没法检索到, 错误信息以下图
  • 提交本地索引的过程当中遇到相似错误则能够, 直接忽略提交便可, 可是其余的错误信息, 切记须要修改好, 警告能够忽略, 可是错误信息不能忽略(依赖私有库的问题除外)
// 提交本地私有索引库须要忽略警告的命令
pod repo push TitanjunSpec MainMoudle.podspec --allow-warnings
复制代码

podspec

相关参考


欢迎您扫一扫下面的微信公众号,订阅个人博客!

微信公众号
相关文章
相关标签/搜索