CocoaPods进阶:本地包管理

粉笔网的iOS工程师唐巧曾经写过一篇blog《使用CocoaPods来做iOS程序的包依赖管理》介绍了基本的CocoaPods使用方法。本文将另外谈一谈如何使用CocoaPods进行本地的包管理。建议没有接触过CococaPods的朋友先阅读一下唐巧的blog。

为什么要进行本地的包管理

  • 有的时候CocoaPods的spec版本过旧,pull request没有及时merge,导致我们无法利用CocoaPods使用较新的代码版本;
  • 有的时候我们的一些代码不是开源的,或者暂时不想放到Github上。我们更想使用CocoaPods引用本地的代码;

使用CocoaPods里没有的第三方库新版本

这里我们以PlayHavenSDK为例介绍一下。我们在CocoaPods / Spec这个repository里面可以看到,PlayHavenSDK的版本是1.11.0。而playhaven / sdk-ios里面的tag,已经有了1.12.1这个版本。CocoaPods的Spec repository已经落后了两个版本。这时我们想使用最新版,需要的就是一个更新的spec。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Pod::Spec.new do |s|
s.name = 'PlayHavenSDK'
s.version = '1.12.1'
s.license = 'MIT'
s.summary = 'PlayHaven is a real-time mobile game marketing platform to help you take control of the business of your games.'
s.homepage = 'http://playhaven.com'
s.author = { 'Sam Stewart' => 'sam@playhaven.com' }
s.source = { :git => 'https://github.com/playhaven/sdk-ios.git', :tag => '1.12.1' }
s.description = "PlayHaven is a real-time mobile game marketing platform to help you take control of the business of your games. Acquire, retain, re-engage, and monetize your players with the help of PlayHaven's powerful marketing platform. Integrate once and embrace the flexibility of the web as you build, schedule, deploy, and analyze your in-game promotions and monetization in real-time through PlayHaven's easy-to-use, web-based dashboard. An API token and secret is required to use this SDK. These tokens uniquely identify your app to PlayHaven and prevent others from making requests to the API on your behalf. To get a token and secret, please visit the PlayHaven developer dashboard at https://dashboard.playhaven.com."
s.platform = :ios
# PlayHaven includes prefixed versions of SBJson and OpenUDID
s.source_files = 'Cache', 'src', 'WaterWorks', 'JSON', 'OpenUDID'
s.frameworks = 'SystemConfiguration', 'CFNetwork', 'StoreKit', 'CoreGraphics', 'QuartzCore'
s.weak_frameworks = 'AdSupport'
end

这里我们注意到s.source这一行配置,指向了playhaven/sdk-ios.git仓库的1.12.1这个tag,表示这个spec将使用这个tag的代码。我们将它保存到本地的一个目录中,如~/Desktop/PlayHavenSDK/PlayHavenSDK.podspec

我们回到Xcode project目录中,打开Podfile,添加pod 'PlayHavenSDK', :podspec => '~/Desktop/PlayHavenSDK/PlayHavenSDK.podspec',接着运行pod update即可。

PS: 当然这个podspec也可以不放在本地,比如放在gist上。

使用CocoaPods管理本地代码

这种情况稍微复杂一步,除了指定podspec,还需要准备一个本地要使用的git repository。我们以Chartboost为例来进行说明。

首先我们新建一个名为~/Desktop/ChartboostSDK/的目录,然后执行git init初始化这个git repository。

接着我们去Chartboost官方网站下载最早新的SDK。将它放进这个目录中,然后执行git add . && git commit -m"Add new SDK"

这样我们这个目录已经成为一个git repository,里面是最新的Chartboost SDK。

这时我们仍然需要一个podspec文件,来说明我们从哪个仓库来获取代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Pod::Spec.new do |s|
s.name = 'ChartboostSDK'
s.version = '3.1.1'
s.license = 'Commercial'
s.summary = 'ChartboostSDK for showing ads and more apps pages, and tracking analytics and in-app purchase revenue.'
s.homepage = 'https://chartboost.com/'
s.author = { 'Chartboost' => 'https://chartboost.com/' }
s.source = { :git => '~/Desktop/ChartboostSDK' }
s.platform = :ios
s.source_files = '**/*.h'
s.preserve_paths = '**/*.a'
s.library = 'Chartboost'
s.xcconfig = { 'LIBRARY_SEARCH_PATHS' => '"$(PODS_ROOT)/ChartboostSDK/Chartboost"' }
s.weak_frameworks = 'AdSupport', 'StoreKit'
s.frameworks = 'QuartzCore', 'SystemConfiguration', 'CoreGraphics'
end

我们运行ls -lh | awk '{print $9}',ChartboostSDK目录的结构显示如下:

1
2
3
4
CBAnalytics.h
Chartboost.h
ChartboostSDK.podspec
libChartboost.a

除了两个.h,一个.a,还有一个podspec文件。

接着我们回到Xcode proj所在的文件夹中,编辑Podfile,添加pod 'ChartboostSDK', :local => '~/Desktop/ChartboostSDK'。这里的local表明从本地的git仓库里获取代码。

最后我们运行pod update,大功告成。

CocoaPods小结

上面的两种情况,简单来说:

  • 需要使用最新的开源代码/库,但没最新的spec
  • 需要使用私有代码/库,需要对应的私有的spec

对于第一种情况,建议大家可以给CocoaPods / Specs提交一个pull request。

使用CocoaPods只需要知道两件事情:

  • podspec:一个pod的配置是什么,pod的代码放在哪里
  • Podfile:项目依赖哪个pod,以何种方式依赖,它的podspec放在哪里

这里podspec和git repository都非常灵活,可以放在本地,也可以放到github/gist上。代码仓库甚至可以不使用git而直接使用一个zip压缩包。

使用CocoaPods可以把多们从繁重的配置和代码管理中解脱出来,而且可以少犯错误。比如Deployment Target设置为5.0,但App中需要使用AdSupport.framework,如果忘记设置为optional则所有5.x的设备运行时都会crash。对于这种情况CocoaPods在spec提供了weak_frameworks的配置选项。同时CocoaPods能够保证库的依赖关系,而不会出现几个项目依赖版本不一致的情况。

PS: 最近为了UDID更新的同学们可别犯AdSupport.framework这个错误,后果很严重。

希望这个blog对大家使用CocoaPods有所帮助。

赶个时髦,祝大家一帆风顺

一帆风顺

附小广告一则:唱吧iOS团队诚招iOS工程师,推荐成功即奖励6000元现金或iPhone 6一部,详见这篇blog