背景
之前写过一篇 ,这篇作为续集,聊一聊使用 Cocoapods
在iOS平台组件化的实现和集成。
结果
本文中的两个例子可以在 项目中找到。
工具介绍
Cocoapods
是iOS/osx平台的开发库管理工具,简单的配置然后执行安装命令 Cocoapods
会自动去下载第三方库并且做好相应的配置,简化了引入第三方库的流程,让开发更简单高效,是iOS开发的必备工具,使用 Cocoapods
作为组件化的工具是一个不错的选择。
安装和设置
安装和设计可以参考这篇文章:
实现
简单项目组件化
以一个测试模块解耦的场景实现简单项目的组件化,主要包含以下内容
- Pod库项目创建
- 最基础podspec文件的编写的解释
- 客户端集成
创建项目
使用 pod lib create
创建项目,会遇到几个需要输入的地方,具体的解释看代码段中的注释
➜ DevPods pod lib create PTTestKitCloning `https://github.com/CocoaPods/pod-template.git` into `PTTestKit`.Configuring PTTestKit template.------------------------------To get you started we need to ask a few questions, this should only take a minute.If this is your first time we recommend running through with the guide: - http://guides.cocoapods.org/making/using-pod-lib-create.html ( hold cmd and double click links to open in a browser. )# 使用的语言What language do you want to use?? [ Swift / ObjC ] > Objc# 是否包好测试工程,指定YES用于模块化的解耦测试Would you like to include a demo application with your library? [ Yes / No ] > yes# 集成的测试模块,不需要指定NoneWhich testing frameworks will you use? [ Specta / Kiwi / None ] > None# UI测试模块,不需要指定NoWould you like to do view based testing? [ Yes / No ] > No# 指定类前缀What is your class prefix? > PTRunning pod install on your new library.
podspec 文件编写
一个简单的 podspec 文件如下,具体字段的解释查看代码中的注释即可
Pod::Spec.new do |s| s.name = 'PTTestKit' s.version = '0.1.0' s.summary = 'Wow PTTestKit.'# This description is used to generate tags and improve search results.# * Think: What does it do? Why did you write it? What is the focus?# * Try to keep it short, snappy and to the point.# * Write the description between the DESC delimiters below.# * Finally, don't worry about the indent, CocoaPods strips it! # 长的描述信息 s.description = <<-DESCWow this is a amazing kit,Enjoy yourself! DESC # 提交到git服务区的项目主页,没提交可以指定任意值,但需要保留这一项,否则会报错 # attributes: Missing required attribute `homepage`. s.homepage = 'https://github.com/flypigrmvb/PTTestKit' # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' # 授权文件 s.license = { :type => 'MIT', :file => 'LICENSE' } # 用户信息 s.author = { 'flypigrmvb' => '862709539@qq.com' } # 提交到git上的源码路径,没提交可以指定任意值,但需要保留这一项,否则会报错 # attributes: Missing required attribute `source`. s.source = { :git => 'https://github.com/flypigrmvb/PTTestKit.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' # 指定最低的ios版本 s.ios.deployment_target = '8.0' # 源文件的路径 s.source_files = 'PTTestKit/Classes/**/*' # 公共的头文件,按需设置 s.public_header_files = 'PTTestKit/Classes/Public/**/*.h' # 私有的头文件,按需设置 s.private_header_files = 'PTTestKit/Classes/Private/**/*.h' # 依赖的系统Framework,按需设置 # s.frameworks = 'UIKit', 'MapKit' # 依赖其他的pod库,按需设置 # s.dependency 'AFNetworking', '~> 2.3'end
客户端集成
如果在创建Pod库项目的步骤集成了 Example 测试项目,在测试项目下的podfile默认包含了当前的Pod库项目
#use_frameworks!target 'PTTestKit_Example' do pod 'PTTestKit', :path => '../' target 'PTTestKit_Tests' do inherit! :search_paths endend
切换到测试项目目录下,运行 pod install
命令,完了之后测试项目集成了Pod项目。下面是在测试项目中使用Pod库项目中一些功能的简单例z
#import "PTViewController.h"#import// !!private header 可以导入#import // !!报错//#import @interface PTViewController ()@end@implementation PTViewController- (void)viewDidLoad{ [super viewDidLoad]; [self addActionWithName:@"Test" callback:^{ NSLog(@"===="); }]; [self addActionWithName:@"PrivateFile" callback:^{ [PrivateFile test]; }];}- (void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [PrivateFile test];}@end
分模块组件化
以一个第三发组件集成的场景为例,实现分模块组件化,主要包含以下内容:
- 创建核心模块
- 创建子模块
- 客户端集成
pod库项目的创建流程和简单模块组件步骤一致,不在赘述
podspec 文件编写
该文件创建了一个Core模块,用于存放抽象的接口、基类以及一些公用的工具类和头文件,以及几个子模块用于具体的第三方平台的实现。具体的内容可以查看以下代码中的注释内容
Pod::Spec.new do |s| s.name = 'PTThirdPlatformKit' s.version = '0.1.0' s.summary = 'A short description of PTThirdPlatformKit.'# This description is used to generate tags and improve search results.# * Think: What does it do? Why did you write it? What is the focus?# * Try to keep it short, snappy and to the point.# * Write the description between the DESC delimiters below.# * Finally, don't worry about the indent, CocoaPods strips it! s.description = <<-DESCTODO: Add long description of the pod here. DESC s.homepage = 'https://github.com/flypigrmvb/PTThirdPlatformKit' # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'flypigrmvb' => '862709539@qq.com' } s.source = { :git => 'https://github.com/flypigrmvb/PTThirdPlatformKit.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' s.ios.deployment_target = '8.0' # 设置默认的模块,如果在pod文件中导入pod项目没有指定子模块,导入的是这里指定的模块 s.default_subspec = 'Core' # 定义一个核心模块,用户存放抽象的接口、基类以及一些公用的工具类和头文件 s.subspec 'Core' do |subspec| # 源代码 subspec.source_files = 'PTThirdPlatformKit/Classes/**/*' # 配置系统Framework subspec.frameworks = 'CoreMotion' subspec.dependency 'SDWebImage' # 添加依赖的系统静态库 subspec.libraries = 'xml2', 'z', 'c++', 'stdc++.6', 'sqlite3' end # 支付宝模块 s.subspec 'AlipayManager' do |subspec| # 源代码 subspec.source_files = 'PTThirdPlatformKit/AlipayManager/**/*' # 添加资源文件 subspec.resource = 'PTThirdPlatformKit/AlipayManager/**/*.bundle' # 添加依赖第三方的framework subspec.vendored_frameworks = 'PTThirdPlatformKit/AlipayManager/**/*.framework' # 添加依赖系统的framework subspec.frameworks = 'CoreTelephony', 'SystemConfiguration' # 依赖的核心模块 subspec.dependency 'PTThirdPlatformKit/Core' end # QQ模块 s.subspec 'TencentManager' do |subspec| # 源代码 subspec.source_files = 'PTThirdPlatformKit/TencentManager/**/*' # 添加资源文件 subspec.resource = 'PTThirdPlatformKit/TencentManager/**/*.bundle' # 添加依赖第三方的framework subspec.vendored_frameworks = 'PTThirdPlatformKit/TencentManager/**/*.framework' # 添加依赖系统的framework subspec.frameworks = 'SystemConfiguration' # 依赖的核心模块 subspec.dependency 'PTThirdPlatformKit/Core' end # 微博模块 s.subspec 'WeiboManager' do |subspec| # 源代码 subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*' # 依赖的微博pod库 subspec.dependency 'WeiboSDK' subspec.dependency 'PTThirdPlatformKit/Core' end # 微信模块 s.subspec 'WXManager' do |subspec| # 源代码 subspec.source_files = 'PTThirdPlatformKit/WXManager/**/*' # 依赖的微信pod库 subspec.dependency 'WechatOpenSDK' subspec.dependency 'PTThirdPlatformKit/Core' endend
客户端集成
podfile文件如下,可以导入主模块和任意的子模块的组合
#use_frameworks!platform :ios, '8.0'target 'PTThirdPlatformKit_Example' do pod 'PTTestKit', :path => '../../PTTestKit' # 主模块 pod 'PTThirdPlatformKit', :path => '../' # 子模块快 pod 'PTThirdPlatformKit/AlipayManager', :path => '../' pod 'PTThirdPlatformKit/TencentManager', :path => '../' pod 'PTThirdPlatformKit/WeiboManager', :path => '../' pod 'PTThirdPlatformKit/WXManager', :path => '../' endtarget 'PTThirdPlatformKit_Example_Developer' do pod 'PTTestKit', :path => '../../PTTestKit' pod 'PTThirdPlatformKit', :path => '../' pod 'PTThirdPlatformKit/AlipayManager', :path => '../' pod 'PTThirdPlatformKit/TencentManager', :path => '../' pod 'PTThirdPlatformKit/WeiboManager', :path => '../' pod 'PTThirdPlatformKit/WXManager', :path => '../' end
遇到问题
开发中的Pod库依赖另一个Pod库的处理
参考:
podspec文件添加添加s.vendored_frameworks = 'PTDataModule/Frameworks/*.framework'
ARC环境中配置非ARC文件
需要用到podspec规则中的subspec和requires_arc
参考:s.requires_arc = true # no arc files rules non_arc_files = 'PTDataModule/Classes/**/JSONKit.{h,m}' s.exclude_files = non_arc_files s.subspec 'no-arc' do |sna| sna.requires_arc = false sna.source_files = non_arc_files end
PrefixHeader
参考:
podspec指定 PTDataModule-prefixheader.pch 文件
s.prefix_header_file = 'PTDataModule/SupportFiles/PTDataModule-prefixheader.pch'
PTDataModule-prefixheader.pch 文件内容
#import "UtilMacro.h"#import "DebugConfig.h"#import "TIMAdapter.h"
有个坑,使用pod install 之后自定义的pch文件在项目中找不到了,但是内容会添加到PTDataModule-prefix.pch文件中
可以使用这种方式,直接把需要导入的头文件使用参数的方式指定
参考:spec.prefix_header_contents = '#import', '#import '
Pod 更新不成功问题
[!] The 'Pods-PTThirdPlatformKit_Example' target has transitive dependencies that include static binaries: (/Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WechatOpenSDK/OpenSDK1.8.0/libWeChatSDK.a and /Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WeiboSDK/libWeiboSDK/libWeiboSDK.a)
解决办法:
#use_frameworks! (注释这个)添加.a静态库和对应的头文件 PTBehaviorStat
s.public_header_files = 'PTBehaviorStat/Classes/**/*.h', 'PTBehaviorStat/vendor/**/*.h's.vendored_library = 'PTBehaviorStat/**/*.a'
pod lib create 创建库拉取GitHub模板数据慢的问题
--template 参数指定本地的 模板数据
Pod开发库依赖本地开发库的问题
参考:
比如Pod开发库A依赖Pod开发库B,依赖的信息填写如下即可,不需要指定路径获取其他信息s.dependency 'DevLibB'
在测试工程或者客户端工程的的podfile文件中需要显示的导入DevLibB,这样即可
pod 'DevLibB', :path => '../../DevLibB'
源文件没有配置对会找不到
subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*'
如果配置(如下所示)是错误的路径,在客户端是找不到这个类的,需要检查源文件配置的是否正确
subspec.source_files = 'PTThirdPlatformKit/WeiboManager111/**/*'
总结
以上是我在使用cocoapods做组件化集成实践的一些总结和遇到的一些问题,希望对有需要的朋友有帮助。