模块化之路(实验)
一直以来,我们都在尝试让代码尽可能高内聚、低耦合。比如我们将MVP框架改成MVVM框架,以解决Controller层代码臃肿不堪,让model和view尽可能不要耦合。再比如,我们之前尝试的路由,是为了让Controller与Controller之间不要有太多的代码交集。而模块化实际上就是为了让模块与模块直接相对独立。
模块化优势: 各模块代码与资源独立使用与维护、独立测试、各模块业务需求利于使用与维护、加快二次启动速度(使用framework的前提下)
一
cocoapod 私有库实践
cocopod 是一个第三方库依赖工具
要完成一个pod私有化全过程,需要三个仓库(主项目仓库、pod库仓库、PodDemo项目仓库)、两个项目(主项目、PodDemo项目)
1、在repo下创建私有库(要远程仓库)
cd到cocoapods目录下查看本地的仓库,会发现大概的文件路径是 ~/.cocoapods/repos/master … 这是系统中有使用到cocoapod后,在install pod的时候,会从cocoapod官网下载一份所有的库的podspec文件集合。这些都是共有库的资源。所有项目需要使用pod库的时候会在这里索引,如果search不到,那就需要更新一下你的本地索引了。
因此,创建私有库也是相同道理,就是在repos下创建一个类似master的私有的索引库。所以,首先去个人的远程仓库(比如gitlab)创建一个git仓库。比如是git地址是:https://xx@gitlab.btclass.cn/xx/BTCore.git
然后使用pod命令在Terminal执行:
$pod repo add BTCore https://xx@gitlab.btclass.cn/xx/BTCore.git
执行成功后,就可以在 ~/.cocoapods/repos/目录下看到BTCore文件夹了。这个就是私有pod库最终的索引。如果和同事合作的话,也同样执行命令创建出一个repo即可。
OK,这一步就是顺便完成了上面提到的pod库仓库。暂且搁置一旁!
2、创建一个新的PodDemo(要远程仓库)
PodDemo就是讲代码打包成pod库工具,另外它本身是一个完整的测试pod库的项目。在将代码打包的前提需要先代码编译通过,所以可以在demo里尽情调试。
使用pod命令创建一个标准的podDemo项目
$pod lib create BTCoreDemo
创建过程中会提示一些问题,类似:
What platform do you want to use?? [iOS/macOS]
What language do you want to use?/ [Swift/ObjC]
Would you like to include a demo application with your library? [Yes/No]
...
完成后就会生成一个项目
创建出来的项目的文件结构会包含Example和Pod部分。类似:
BTCoreDemo
|——_pods.xcodeproj
|——BTCoreDemo
| |——Assets //放需要pod里的资源文件
| |——Classes //放pod库代码文件
|
|——Example //存放完整的项目文件(除pod库之外)
| |——BTCoreDemo //代码文件,比如使用pod库的文件
| |——BTCoreDemo.xcodeproj
| |——BTCoreDemo.xcworkspace
| |——Podfile //库使用到的第三方
| |——Podlock
| |——Pods //依赖的第三方
| |——Tests
|
|——BTCoreDemo.podspec //最重要的pod配置文件
3、将代码移到Demo中,编译成功后,update编译成pod库,并及时将代码更新到远程仓库,注意设置tag
接下来将解耦后的独立代码放到Classes文件中
cd 到Example目录下, 执行
$pod update //完成后会将class里的东西打包成pod库
完成之后,用xcode打开工程,会在pods工程下看到Development Pods文件,这里的BTClassDemo就是之后使用的最终的pod库的内容。
但是不是将代码移过来就完成了,首先需要验证pod库,而这第一步就是保证当前Demo工程编译通过。
4、配置podspec(最重要)
在编译通过的前提下,就可以对pod进行一些定制化的操作。
Pod::Spec.new do |s|
s.name = 'BTCoreDemo' #库名称
s.version = '0.0.1' #version要和git上的tag进行对应
s.summary = 'BT学院App中基础文件、公共文件、第三方库等集成框架库'
s.description = <<-DESC
'BT学院App中基础文件、公共文件、第三方库等集成框架库,gogogogo'
DESC
s.homepage = 'https://caifan@gitlab.btclass.cn/caifan/BTCoreDemo' #随便一网址
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'caifan' => '2998000457@qq.com' }
s.source = { :git => 'https://caifan@gitlab.btclass.cn/caifan/BTCoreDemo.git', :tag => '0.0.1' } #git地址,当前demo的git地址,tag则要和上面的version一样
s.platform = :ios,'9.0' #平台就iOS版本
s.requires_arc = true #是否支持arc
s.prefix_header_file = 'BTCoreDemo/Classes/prefixHeader.h' #pch头文件,注意:写完prefixHeader.h后,要执行pod update,成功后才会将prefixHeader.h文件的内容copy一份到Support Files下的.pch中。否则项目中使用不了
s.frameworks = 'UIKit', 'AVFoundation','QuartzCore' #对外依赖的库
#subspec: 创建子分支,每个子分支对应一层文件夹,注意:虽然在当前Demo中pod库看似有文件层次,但是当最终生成pod库之后,只会存在子分支的文件层次,各子分支里的所有文件都会被拍扁成一个层级文件
#source_files: 子分支的文件路径,这里有时候会出现找不到文件的情况,所以要实时更新,多个文件用,分割开,**/*表示子文件夹下所有的文件和文件夹
#public_header_files: 子分支的头文件路径。
#dependency: 依赖,子分支之间的依赖、对第三方的依赖
#resource: 资源路径
s.subspec 'Kit' do |kit|
kit.source_files = 'BTCoreDemo/Classes/Kit/**/*',
kit.public_header_files = 'BTCoreDemo/Classes/Kit/**/*.h'
kit.dependency 'BTCoreDemo/ThirdParty'
end
s.subspec 'ThirdParty' do |thirdparty|
thirdparty.source_files = 'BTCoreDemo/Classes/ThirdParty/**/*'
thirdparty.public_header_files = 'BTCoreDemo/Classes/ThirdParty/**/*.h'
thirdparty.resource = 'BTCoreDemo/Assets/SVProgressHUD.bundle'
end
s.dependency 'Masonry', '~> 1.0.2'
end
注意,每次完成后,需要直接pod update,这样pod里的文件才会重新整理更新。
然后给podspec打上tag。注意tag必须和version一致
$cd .. //这里是从Example文件夹退到上一层,含有podspec文件的层级
$git tag 0.0.1
$git push --tag
最后,进行验证:
$pod lib lint
如果要忽略警告,加上—allow-warnings,如果使用了第三方库,则加上—use-libraries。
如果验证不通过的话,是没法push到repos里的。
而验证通过的前提就是不能有任何error。(这才是整个项目最蛋疼的地方)
5、将编译验证完成的podspec库push到第一步创建的repo私有库中(完成后会看到私有库的远程仓库也会有一份podspec),在podspec文件层级下进行
$pod repo push BTCoreDemo BTCoreDemo.podspec --allow-warnings
执行完这句后,会在第一步创建的BTCoreDemo下多出一个文件夹,文件夹下是对应版本的podspec。同时第一步创建的远程的git仓库也会多出这些文件。
至此,说明pod库是可用的了。
6、检测是否能search到私有库
$pod search BTCoreDemo
如果搜索不到就先执行:
$rm ~/Library/Caches/CocoaPods/search_index.json
7、将pod成功的私有库添加到原来的项目中
编译原来项目的Podfile,将BTCoreDemo添加进去。
注意,podfile中需要把共有和私有的两个地址都加上。
source 'https://github.com/CocoaPods/Specs.git' # 官方库
source 'https://xx@gitlab.btclass.cn/xx/BTCore.git' #私有库
8、码过留坑
这里整理一下遇到的问题及解决的方案:
1、pod lib lint 中碰到的各种error和warn
ERROR | [iOS] file patterns: The resource_bundles
pattern for SVProgressHUD
did not match any file.
分析:目前总结出现这个问题的原因一般为:1、没有打tag;2、tag与version不一致;3、各种路径错误(这个有可能是它本身会抽,有时候提示路径问题,但是改完倒腾回来就又有用了,也可能是没有掌握到精髓)
—allow-warnings 忽略警告的验证过程
2、资源文件问题bundle
resource和resource_bundles的差异,参考简书
3、subspec分支问题、文件夹问题
目前所知文件夹是没法做层级的,只有分子分支,每个子分支会是一个文件夹。
4、swift混编问题
无论swift文件在哪里,使用#import 导入swift桥接文件
这里的XX指的是pod包的名称,其次要注意的是swift类应该用@