經常使用CocoaPods來管理iOS項目中的第三方庫,但是我們要使用CocoaPods來管理第三方庫,前提是要寫好Podfile文件,通過這個文件來配置第三方庫與項目之間的依賴、版本等信息。
但是,我相信很少有人完整地學習過Podfile的語法規則,包括筆者在寫本篇文章之前。今天,請大家與筆者一起來完整地學習Podfile官方教程。
之前一直想寫來著,因為包括筆者在內并沒有深入學習過它的使用。如果對之不夠了解,如何能做到善用之。因此,下面一起來探討探討吧!
什么是Podfile
官方只有一句話說明什么是Podfile:The Podfile is a specification that describes the dependencies of the targets of one or more Xcode projects.
大概意思是:Podfile文件是一種規則描述,用于描述一或多個Xcode工程的targets之間的依賴。
Podfile可以很簡單:
target 'MyApp' pod 'AFNetworking', '~> 1.0'
也可以很復雜:
platform :ios, '9.0' inhibit_all_warnings! target 'MyApp' do ?pod 'ObjectiveSugar', '~> 0.5' ?target 'MyAppTests' do ? ?inherit! :search_paths ? ?pod 'OCMock', '~> 2.0.1' ?end end post_install do |installer| ?installer.pods_project.pod_targets.each do |target| ? ?puts '#{target.name}' ?end end
這里只是拋磚引玉,繼續往下看,如何一點點地掌握Podfile的語法規則。
Podfile全局配置
目前根據官方文檔說明,Podfile全局配置只有一個命令:
install!
官方說明它的作用是:Specifies the installation method to be used when CocoaPods installs this Podfile.(大概意思是:指定CocoaPods安裝Podfile時所使用的安裝方法)
例如:
install! 'cocoapods', ? ? ? ? :deterministic_uuids => false, ? ? ? ? :integrate_targets => false
目前支持的key有:
:clean :deduplicate_targets :deterministic_uuids :integrate_targets :lock_pod_sources
這個沒有見過任何工程里邊有人使用過,相信99%的人兒都是使用默認的全局配置。對于這幾個key,官方也沒有明確說明其功能!
在我們日常開發中,我們可能永遠不需要使用到此配置命令,因此大家不用太關注它!
Dependencies(依賴)
CocoaPods就是用于管理第三方依賴的。我們通過Podfile文件配置來指定工程中的每個target之間與第三方之間的依賴。
有以下三個命令來管理依賴:
pod 指定特定依賴。比如指定依賴AFNetwroking
podspec 提供簡單的API來創建podspec
target 在我們的工程中,通過target指定所依賴的范圍。
Pod命令
此命令用于指定工程的依賴。我們通過Pod命令指定所依賴的第三方及第三方庫的版本范圍。
永遠使用最新版本
pod 'HYBMasonryAutoCellHeight'
當我們永遠使用遠程倉庫中的最新版本時,我們只需要指定倉庫名即可。當有新的版本發布時,執行pod update命令,會更新至最新的版本。
因為版本之間可能會存在很大的差異,因此我們不應該采用這種方式,而是指定版本范圍或者指定特定版本。
使用固定版本
pod 'HYBLoopScrollView', '2.0'
當我們不希望版本更新,而是固定使用指定的版本時,我們應該這么寫法。當遠程有新的版本發布時,pod是不會去更新新版本的。由于版本變化可能較大,因此有時候我們希望這么做的。
指定版本范圍
pod 'HYBUnicodeReadable', '~>1.1.0'
當我們不要求固定版本號,而是指定某個范圍時,我們會像上面這么寫法。我相信大家在工程中見到最多的就是這種寫法了吧。但是,我相信很多朋友并不知道這么寫法的意思是什么。
它的意思是:HYBUnicodeReadable的版本可以是1.1.0到2.0.0,但是不包括2.0.0。
使用這種寫法是很有用的,因此小版本的升級一般是fix bug,當有bug被fix時,我們確實應該更新。從1.9.9升級到2.0.0時,不會去更新到2.0.0版本。我們認為從2.0.0是一個大版本,大版本的發布,通常不是fix bug,而是增加功能或者改動較大。
那么有哪些符號可以指定范圍呢:
= version 要求版本大于或者等于version,當有新版本時,都會更新至最新版本
< version 要求版本小于version,當超過version版本后,都不會再更新
<= version 要求版本小于或者等于version,當超過version版本后,都不會再更新
~> version 比如上面說明的version=1.1.0時,范圍在[1.1.0, 2.0.0)。注意2.0.0是開區間,也就是不包括2.0.0。
使用本地庫
pod 'AFNetworking', :path => '~/Documents/AFNetworking'
如果我們的庫是在本地的,那么我們可以通過這樣的命令來指定。由于是引用目錄,因此外部直接修改目錄中的內容,CocoaPods也會更新到最新的,所以也挺不錯的!
通過倉庫的podspec引入
Sometimes you may want to use the bleeding edge version of a Pod. Or a specific revision. If this is the case, you can specify that with your pod declaration.
當我們需要使用庫的混合邊緣版本,或者指定的修訂版本,我們可以通過指定像下面這樣的聲明。
使用倉庫的master(主干):
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git'
不是使用master,而是使用指定的分支:
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :branch => 'dev'
使用指定的tag(標簽,發布庫的版本時,通常版本號與tag號是一致的):
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :tag => '0.7.0'
使用指定的提交版本:
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :commit => '082f8319af'
官方明確說明要求podspec在根目錄下:
The podspec file is expected to be in the root of the repository, if this library does not have a podspec file in its repository yet, you will have to use one of the approaches outlined in the sections below.
也就是說與工程同級!比如AFNetworking中的podspec文件與庫目錄是同級的,都在根目錄下!
從外部podspec引入
pod 'JSONKit', :podspec => 'https://example.com/JSONKit.podspec'
如上,當我們發布到CocoaPods時,如果沒有podspec不是在根目錄下,而是在外部,可以通過’:podspec’命令來指定外部鏈接。
podspec
Use just the dependencies of a Pod defined in the given podspec file. If no arguments are passed the first podspec in the root of the Podfile is used. It is intended to be used by the project of a library. Note: this does not include the sources derived from the podspec just the CocoaPods infrastructure.
大概意思是:使用給定的podspec所指定的pod依賴。如果沒有指定參數,根目錄下的podspec會被使用。
正常情況下,我們并不需要指定,一般所開源出來的庫的podspec都是在根目錄下,所以可放心地使用,不用考慮太多。
例如:
// 不指定表示使用根目錄下的podspec,默認一般都會放在根目錄下 podspec // 如果podspec的名字與庫名不一樣,可以通過這樣來指定 podspec :name => 'QuickDialog' // 如果podspec不是在根目錄下,那么可以通過:path來指定路徑 podspec :path => '/Documents/PrettyKit/PrettyKit.podspec'
target
Defines a CocoaPods target and scopes dependencies defined within the given block. A target should correspond to an Xcode target. By default the target includes the dependencies defined outside of the block, unless instructed not to inherit! them.
大概意思是:在給定的塊內定義pod的target(Xcode工程中的target)和指定依賴的范圍。一個target應該與Xcode工程的target有關聯。默認情況下,target會包含定義在塊外的依賴,除非指定不使用inherit!來繼承(說的是嵌套的塊里的繼承問題)
例子:
我們指定HYBTestProject這個target可以訪問HYBMasonryAutoCellHeight庫:
target 'HYBTestProject' do ?pod 'HYBMasonryAutoCellHeight', '~>1.1.0' end
指定HYBTestProject這個target可以訪問SSZipArchive,但是它不能訪問Nimble;但是,HYBTestProjectTests這個target可以訪問Nimble,默認是繼承塊外的,而且這里指定了inherit!繼承,因此它也能訪問SSZipArchive:
target 'HYBTestProject' do ?pod 'SSZipArchive' ?target 'HYBTestProjectTests' do ? ?inherit! :search_paths ? ?pod 'Nimble' ?end end
target塊內可以有多個target子塊:
target 'ShowsApp' do ?pod 'ShowsKit' ?# 可以訪問ShowsKit ShowTVAuth,其中ShowsKit是繼承于父層的 ?target 'ShowsTV' do ? ?pod 'ShowTVAuth' ?end ?# 可以訪問Specta Expecta ?# 同時也可以訪問ShowsKit,它是明確指定繼承于父層的所有pod ?target 'ShowsTests' do ? ?inherit! :search_paths ? ?pod 'Specta' ? ?pod 'Expecta' ?end end
注意:Inheriting only search paths。也就是說inherit! :search_paths這是固定的寫法。
Target configuration
這里的配置會使用和控制工程的生成。
platform
platform :ios, '7.0' platform :ios
如果沒有指定版本,官方默認值說明如下:
CocoaPods provides a default deployment target if one is not specified. The current default values are 4.3 for iOS, 10.6 for OS X, 9.0 for tvOS and 2.0 for watchOS.
也就是說,若不指定平臺版本,各平臺默認值如下:
iOS:4.3
OS X:10.6
tvOS:9.0
watchOS:2.0
project
默認情況下是沒有指定的,當沒有指定時,會使用Podfile目錄下與target同名的工程:
# MyGPSApp只有在FastGPS工程中才會鏈接 target 'MyGPSApp' do ?project 'FastGPS' ?... end # MyNotesApp這個target只有在FastNotes工程中才會鏈接 target 'MyNotesApp' do ?project 'FastNotes' ?... end
一般情況下,我們不指定project,直接使用:
target 'MyApp' do ? pod ... end
inhibit_all_warnings!
inhibit_all_warnings!命令是不顯示所引用的庫中的警告信息。我們可以指定全局不顯示警告信息,也可以指定某一個庫不顯示警告信息:
pod 'SSZipArchive', :inhibit_warnings => true
use_frameworks!
通過指定use_frameworks!要求生成的是framework而不是靜態庫。
workspace
默認情況下,我們不需要指定,直接使用與Podfile所在目錄的工程名一樣就可以了。如果要指定另外的名稱,而不是使用工程的名稱,可以這樣指定:
workspace 'MyWorkspace'
source
source是指定pod的來源。如果不指定source,默認是使用CocoaPods官方的source。通常我們沒有必要添加。
// 如果不想使用官方的,而是在別的地方也有,可以這樣指定 source 'https://github.com/artsy/Specs.git' // 默認是官方的source source 'https://github.com/CocoaPods/Specs.git'
Hooks
Hooks可以叫它為勾子吧,與swizzling特性差不多,就是在某些操作之前,先勾起,而且讓它執行我們特定的操作。
plugin
Specifies the plugins that should be used during installation.
Use this method to specify a plugin that should be used during installation, along with the options that should be passed to the plugin when it is invoked.
例如,指定在安裝期間使用cocoapods-keys和slather這兩個插件:
plugin 'cocoapods-keys', :keyring => 'Eidolon' plugin 'slather'
pre_install
This hook allows you to make any changes to the Pods after they have been downloaded but before they are installed.
當我們下載完成,但是還沒有安裝之時,會勾起來,然后可以通過pre_install指定要做的事,做完后才進入安裝階段。
比如:在下載完成但未安裝之前,我們就可以指定在干些什么:
pre_install do |installer| ?# Do something fancy! end
post_install
既然有pre_install命令,自然會想到還有一個與之對應的命令。
This hook allows you to make any last changes to the generated Xcode project before it is written to disk, or any other tasks you might want to perform.
當我們安裝完成,但是生成的工程還沒有寫入磁盤之時,我們可以指定要執行的操作。
比如,我們可以在寫入磁盤之前,修改一些工程的配置:
post_install do |installer| ?installer.pods_project.targets.each do |target| ? ?target.build_configurations.each do |config| ? ? ?config.build_settings['GCC_ENABLE_OBJC_GC'] = 'supported' ? ?end ?end end
def
我們還可以通過def命令來聲明一個pod集:
def 'CustomPods' ? pod 'IQKeyboardManagerSwift' end
然后,我們就可以在需要引入的target處引入之:
target 'MyTarget' do ? CustomPods end
這么寫的好處是:如果有多個target,而不同target之間并不全包含,那么可以通過這種方式來分開引入。
逗視項目的Podfile
下面是逗視項目的Podfile,這是經過筆者整理的:
platform :ios, '8.0' use_frameworks! inhibit_all_warnings! def shared_pods ?pod 'Alamofire', '~> 3.0' ?pod 'Kingfisher', '~> 1.6' ?pod 'MJRefresh' ?pod 'SDCycleScrollView','~> 1.3' ?pod 'APParallaxHeader' ?pod 'RoundImageView', '~> 1.0.1' ?pod 'StrechyParallaxScrollView', '~> 0.1' ?pod 'TextFieldEffects' ?pod 'IQKeyboardManagerSwift' ?pod 'SwiftyJSON' ?pod 'Validator' ?pod 'Qiniu', '~> 7.0' ?pod 'Google-Mobile-Ads-SDK', '~> 7.0' end target 'ds_ios' ?do ?shared_pods end