创建SDK项目
1、打开终端到相应的目录下执行pod lib create sdkName,sdkName是SDK名称,执行之后看到如下信息:
pod lib create TestSDK
Cloning `https://github.com/CocoaPods/pod-template.git` into `TestSDK `.
Configuring TestSDK 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:
- https://guides.cocoapods.org/making/using-pod-lib-create.html
( hold cmd and click links to open in a browser. )
What platform do you want to use?? [ iOS / macOS ]
2、选择平台,根据提示输入iOS或者macOS,这里我们选择iOS:
What platform do you want to use?? [ iOS / macOS ]
> iOS
3、选择编程语言。这里我们选择ObjC,执行:
What language do you want to use?? [ Swift / ObjC ]
> ObjC
4、选择是否需要demo。为了方便自测,我们需要一个demo,选择Yes、执行:
Would you like to include a demo application with your library? [ Yes / No ]
> Yes
5、选择测试框架。这里我们选着None,继续执行:
Which testing frameworks will you use? [ Specta / Kiwi / None ]
> None
6、选择是否需要集成基于view的测试框架。这里我们选择No,继续执行:
Would you like to do view based testing? [ Yes / No ]
> No
7、设置项目代码前缀。这里根据自己需要设置,也可以不设置。执行之后就会创建并自动打开一个xcode工程:
What is your class prefix?
>
8、工程结构
Example是demo。SDK源码目录在TestSDK->Classes,资源文件TestSDK->Assets。
9、自动生成Podfile文件,并且指定了SDK的路径到本地路径path:
use_frameworks!
platform :ios, '9.0'
target 'TestSDK_Example' do
pod 'TestSDK', :path => '../'
target 'TestSDK_Tests' do
inherit! :search_paths
end
end
SDK开发
SDK源码编写
在TestSDK->Classes目录下添加代码文件。当资源文件代码文件或者podspec有更新时直接pod install就可以了。
podspec文件编写
Pod::Spec.new do |s|
s.name = 'TestSDK'
s.version = '0.1.0'
s.summary = 'A short description of TestSDK.'
# 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 = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://github.com/ksxx.com/TestSDK'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { '123@126.com' => '123456@kingsoft.com' }
s.source = { :git => 'https://github.com/ksxx.com/TestSDK.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '9.0'
# 代码文件
s.source_files = 'Classes/**/*'
# public头文件
s.public_header_files = 'Classes/**/*.h'
# 依赖的系统frameworks
s.frameworks = 'UIKit', 'MapKit'
# 依赖的系统.a文件
s.libraries = 'c++', 'resolv', 'stdc++.6.0.9'
# 通过Pod依赖的第三方库,多个库就多个s.dependency
s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'SDWebImage'
# 手动依赖第三方framework
s.vendored_frameworks = 'Classes/b/*.framework', 'TestSDK/Classes/a/*.framework'
# 手动依赖第三方.a文件
s.vendored_libraries = 'Classes/a/*.a','Classes/b/*.a'
# 资源文件打包成bundle,避免资源文件冲突
s.resource_bundles = {
'TestResourceBundle' => ['Assets/Resource/*']
'TestImgesBundle' => ['Assets/Images/*.png']
}
# 使用resources方式引用资源文件
# spec.resources = ['Assets/Images/*.png', 'Assets/Resource/*']
# 配置xcode的other flag
s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
# 指定SDK为静态库
s.static_framework = true
#支持系统版本
s.ios.deployment_target = '9.0'
# 子模块ModelA
s.subspec 'ModelA' do |a|
a.source_files = 'Classes/ModelA/**/*.{h,m}'
a.public_header_files = 'Classes/ModelA/*.h'
a.dependency 'CocoaAsyncSocket', '7.6.3'
a.libraries = 'c++', 'resolv'
a.frameworks = 'CoreBluetooth', 'ExternalAccessory'
a.vendored_frameworks = 'Classes/Frameworks/ModelA.framework'
a.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
end
# 子模块ModelB
s.subspec 'ModelB' do |b|
b.source_files = 'Classes/ModelB/**/*.{h,m}'
b.public_header_files = 'Classes/ModelB/*.h'
b.dependency 'HongDa', '4.8.6'
end
end
Public头文件
这部分主要是SDK对外开放的头文件,如果我们不指定的话,默认就是源代码的全部头文件。所以我们要根据自己需要,开放指定目录下的头文件:
# public头文件
s.public_header_files = 'Classes/**/*.h'
依赖库管理
依赖库系统库和第三方依赖库。系统库都可以通过podspec自动依赖;第三方依赖库依赖包括手动依赖和通过Pod自动依赖。
- 依赖系统库
# 依赖的系统frameworks
s.frameworks = 'UIKit', 'MapKit'
# 依赖的系统.a文件
s.libraries = 'c++', 'resolv', 'stdc++.6.0.9'
- 通过Pod自动依赖第三方库(第三方库支持)。
# 通过Pod依赖的第三方库,多个库就多个s.dependency
s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'SDWebImage'
- 手动依赖第三方库
首先得为第三方库创建一个目录,然后通过podspec指定相应的路径进行依赖:
# 手动依赖第三方framework
s.vendored_frameworks = 'Classes/b/*.framework', 'TestSDK/Classes/a/*.framework'
# 手动依赖第三方.a文件
s.vendored_libraries = 'Classes/a/*.a','Classes/b/*.a'
资源管理
资源管理有两种方式,分别是 resource_bundles 和 resources 两种方式引用。
- 使用resources方式引用资源:
spec.resources = ['Assets/Images/*.png', 'Assets/Resource/*']
使用 resources 之后只会简单的将资源文件 copy 到目标工程(Example 工程),最后和目标工程的图片文件以及其他同样使用 resources 的 Pod 的图片文件,统一一起打包为了一个 Assets.car。使用 resources,如果出现同名的图片,显然是会出现冲突的。
resources 优点:
可以使用 .xcassets 指定资源文件
resources 缺点:
会导致每个库和主工程之间的同名资源冲突,
不需要用硬编码方式获取图片:
[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
所以,一般来说使用 resource_bundles 会更好,不过关于硬编码,还可以再找找别的方式去避免。
- 使用resources方式引用资源resource_bundles:
# 资源文件打包成bundle,避免资源文件冲突
s.resource_bundles = {
'TestResourceBundle' => ['Assets/Resource/*']
'TestImgesBundle' => ['Assets/Images/*.png']
}
使用 resource_bundles 之后会为为指定的资源打一个 .bundle,.bundle包含一个 Assets.car,获取图片的时候要严格指定 .bundle 的位置,很好的隔离了各个库或者一个库下的资源包。避免资源同名冲突。
resource_bundles 优点:
可以使用 .xcassets 指定资源文件
可以避免每个库和主工程之间的同名资源冲突
resource_bundles 缺点:
获取图片时可能需要使用硬编码的形式来获取:[[NSBundle bundleForClass:[self class]].resourcePath stringByAppendingPathComponent:@"/SubModule_Use_Bundle.bundle"]
子模块subspec配置
subspec就相当于SDK中的一个组件。如果我们想把SDK分层不同的模块,使得app在引用SDK时可以按需加载,就可以使用subspec。子模块跟主的spec是一样的,可以理解为它也是一个SDK。比如这里的ModelA:
# 子模块ModelA
s.subspec 'ModelA' do |a|
a.source_files = 'Classes/ModelA/**/*.{h,m}'
a.public_header_files = 'Classes/ModelA/*.h'
a.dependency 'CocoaAsyncSocket', '7.6.3'
a.libraries = 'c++', 'resolv'
a.frameworks = 'CoreBluetooth', 'ExternalAccessory'
a.vendored_frameworks = 'Classes/Frameworks/ModelA.framework'
a.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
end
subspec可以像主spec一样指定自己的source_files、依赖库等等。
那么在Podfile引用的时候可以是:
pod TestSDK/ModelA
SDK提交到CocoaPods
1、注册Trunk账户
注册Trunk账户(邮箱地址建议写成github注册的邮箱,用户名写成github对应的用户名),例如在终端输入:
pod trunk register helloworld@github.com 'helloworld' –verbose
注册命令执行完之后,对应的邮箱地址会收到一封邮件,“请确认您的注册CocoaPods通过点击以下链接:”,打开链接地址完成验证,如果地址不能点击就直接粘贴URL到浏览器上执行。
注册完成之后可以通过pod trunk me查看注册信息。
2、提交代码到git,并打tag,用tag作版本号
(.podspec, LICENSE 这两个文件必须提交到git上)
git add .
git commit -m “1.0.0”
git push
git tag 1.0.0
git push –tags
3、提交之前先验证.podspec文件是否合法
pod spec lint TestSDK.podspec
如果警告一般没有影响,下面如果忽略警告提交可以用–allow-warnings忽略他们:
pod spec lint TestSDK.podspec –allow-warning
4、提交.podspec文件到trunk中
pod trunk push FireRadarSDK.podspec
如果不想有警告,可以用下面的:
pod trunk push FireRadarSDK.podspec –use-libraries –allow-warnings
只要验证通过,提交时一般没有什么问题, 一般会卡在“Updating spec repo ‘master’”, 这时不要关闭终端。
5、查找提交成功的库
先重置一下cocoapods:
pod setup
然后搜索刚才提交的SDK名称:
pod search TestSDK
如果查不到会报错如下 [!] Unable to find a pod with name, author, summary, or description matching。
解决方案: 先删除search_index.json文件,然后再search (文件不存在时会自动下载,根据不同的网络可能要花一会时间,要等)。
rm ~/Library/Caches/CocoaPods/search_index.json
pod search TestSDK
6、从cocoapods移除刚才的SDK
pod trunk delete TestSDK 1.0.0
Pod私有库创建
创建Pod spec 私有库
1、创建一个spec Repo的私有远程仓库和一个存放pod所需的项目工程文件的远程仓库;
比如:https://github.com/NoNameOrganazation/LNSpec.git
2、创建spec Repo;
前往文件夹 ~/.cocoapods/repos 在终端输入:
pod repo add LNSpec https://github.com/NoNameOrganazation/LNSpec.git
3、创建pod的所需的项目工程文件,并上传到远程私有仓库;
git tag -a 0.0.1 -m "更新版本0.0.1"
git push --tags
git tag -d 0.0.1
pod spec lint LNCore.podspec
pod spec lint LNFeed.podspec --sources=https://github.com/CocoaPods/Specs.git,https://github.com/NoNameOrganazation/LNSpec.git
4、向私有的spec Repo远程仓库中提交podspec;
pod repo push LNSpec LNCore.podspec
pod repo
pod repo push LNSpec LNFeed.podspec --sources=https://github.com/CocoaPods/Specs.git,https://github.com/NoNameOrganazation/LNSpec.git --allow-warnings
5、使用自己创建的私有pod库;
Podfile 使用source 指定:
source 'https://github.com/NoNameOrganazation/LNSpec.git'