怎樣在swift中創(chuàng)建一個CocoaPods
你可能對一些比較著名的開源的CocoaPods框架比較熟悉,比如Alamofire、MBProgressHUD。但是有時你可能找不到剛好滿足你需求的pod,也或者你需要把一個大的項目拆分成小的,可重用的組件。
幸運的是,創(chuàng)建你自己的CocoaPods是件很容易的事!
如果你已經(jīng)為你的組件創(chuàng)建了一個Cocoa Touch框架,你已經(jīng)完成了大多數(shù)的比較難的工作。如果你沒有也不要害怕,因為它還是很簡單的。
如果你只是曾經(jīng)創(chuàng)建過iOS app的類的話,那也是可以的。你可以簡單地通過拖拽類或者方法來創(chuàng)建新的pod,這對你專屬的使用會很有意義。
這篇教程是開端,How to Use CocoaPods with Swift(中文 英文)是結(jié)束。如果你之前從沒用過cocoaPods,那么這篇文章絕對是你學(xué)習(xí)的前提。
因此,來一杯熱可可開始學(xué)習(xí)吧!
開始
你的首要客戶是冰淇淋公司。他們的冰淇淋太受歡迎了以至于不能在柜臺接收用戶訂單了。他們雇傭你來做一個漂亮的iOS應(yīng)用,那樣就能讓用戶在他們的iPhone上下訂單了。你開始開發(fā)app了,并且進展得還不錯。
在這里下載開始程序-------這是教程 How to Use CocoaPods with Swift(中文 英文)里的最終版本。
app已經(jīng)有幾個pod依賴文件在下載中,所以你不需要運行pod install來安裝它們。
注意:如果你已經(jīng)學(xué)習(xí)了 How to Use CocoaPods with Swift(中文 英文),那么接下來的部分看起來可能比較熟悉----只是對那篇教程的復(fù)習(xí)。所以可以根據(jù)自己的情況跳過一部分。打開 IceCreamShop.xcworkspace,然后是Main.storyboard,找到Views\Storyboards & Nibs這個分組,看看app是怎樣布局的。
下面是對選擇口味場景的一個大致了解,這是這個應(yīng)用的核心:
- PickFlavorViewController: 處理用戶交互,比如用戶選擇了一個冰淇淋口味。
- PickFlavorDataSource: 是展示冰淇淋口味的collectionview的數(shù)據(jù)源。
- IceCreamView:是一個自定義的view,可以用來展示一種冰淇淋,并且它以Falvor這個模型來支撐。
- ScoopCell:是一個自定義的collectionviewcell,它包含了一個ScoopView,這個view也是以Flavor這個model類來支撐的。
冰淇淋店的高層管理者很喜歡現(xiàn)在的app,但是他們又添加了一些新的需求:冰淇淋零售商需要在他們的app中有選擇個人口味的功能。等等,那沒有在最初的設(shè)計中。但是對于像你這樣厲害的開發(fā)者這沒有問題!
你能猜到怎么做嗎?是的,你需要在他自己的cocoapod中拉入這個方法。
配置你自己的pod
創(chuàng)建一個Xcode工程并且選擇iOS\Framework & Library\Cocoa TouchFramework,然后點擊下一步
輸入RWPickFlavor作為產(chǎn)品名字并且選擇Swift作為開發(fā)語言。選擇下一步。
這篇教程需要你將你的工程創(chuàng)建在~/Documents/Libraries目錄下.在你的主目錄下選擇Documents文件夾。如果你沒有Libraries文件夾,在底部點擊New Folder按鈕并且創(chuàng)建它。
最后,選擇Libraries文件夾并且點擊創(chuàng)建。
你保存你的pod的目錄是很重要的因為在本地開發(fā)期間你需要在podFile中參考你的目錄。
通常,當你使用CocoaPods,你會像下面那樣將依賴性文件加入你的Podfile中
- pod 'PodName', '~> 1.0'
但是當你在開發(fā)自己的CocoaPod,你卻需要指明一個本地的路徑,就像這樣:
- pod 'MyPodName', :path => '~/Path/To/Folder/Containing/My/Pod'
這種方法有兩個好處:
- 它會使用在你電腦上的對應(yīng)的pod的本地文件,而不用從遠端目錄下抓取。
- 通常,你不會修改加入到你的app中的pod,因為這些修改會在下次你運行pod install的時候被覆蓋掉,因為pod會從遠端目錄下重新獲取并且你修改的資源文件也會被覆蓋。通過使用:path => syntax,你可以輕松地修改開發(fā)中的pod而不會被這個過程覆蓋,因為那個路徑就是現(xiàn)在CocoaPod的來源,因此當你再次運行pod install的時候這些修改不會丟失。
然而你可以為你在開發(fā)的pods使用不同的路徑,一般我建議將他們放在~/Documents/Libraries下。如果你有一個團隊在開發(fā)的話這也是一個很好的位置,因為cocoapods知道把“~”擴展為用戶的目錄。因此你不需要在podFile中寫很復(fù)雜的代碼來表示絕對路徑。
你也可以在你創(chuàng)建的cocoapod中引用其他的cocoapod作為依賴性文件-你只需要一個podFile來管理你的cocoaPods依賴性文件。
關(guān)閉Xcode,然后在終端中輸入下面的命令行:
- cd ~/Documents/Libraries/RWPickFlavor
- pod init
- open -a Xcode Podfile
這就創(chuàng)建了一個新的podFile并且在Xcode中打開它。
用下面的內(nèi)容替換新的podFile中的內(nèi)容:
- platform :ios, '8.0'
- use_frameworks!
- target 'RWPickFlavor' do
- pod 'Alamofire', '~> 1.2'
- pod 'MBProgressHUD', '~> 0.9.0'
- end
這就聲明了RWPickerFlavor有外部依賴性文件Alamofire和MBProgressHUD。
保存并且關(guān)閉podFile,然后在終端中輸入下面的命令行:
- pod install
正如你希望的那樣,這就會創(chuàng)建一個workspace并且安裝各種必需的文件
注意:如果pod install命令給出了任何警告,那么你有可能用的是一個老版本的Cocoapods?;趕wift語言的cocoapods,例如Alamofire,要求cocoapods版本在0.36.0及以上。你可以嘗試在終端中輸入以下命令來查看你的cocoapods版本:
- pod --version
如果是那個問題的話,在終端中輸入如下命令來安裝cocoapods的最新版本:
- sudo gem install CocoaPods
輸入以下命令行打開新創(chuàng)建的RWPickFlavor workspace:
- open RWPickflavor.xcworkspace
你的項目導(dǎo)航欄現(xiàn)在看起來應(yīng)該是這樣的:
現(xiàn)在你需要將 IceCreamShop workspace中的幾個文件拷貝到RWPickFlavor中。
#p#
首先,在 RWPickFlavor.xcworkspace 中創(chuàng)建下面的分組來歸類你將要拷貝的文件:
- Categories
- Controllers
- Factories
- Models
- Views(Ice Cream,Storyboards & Nibs)
從IceCreamShop.xcworkspace中的分組到對應(yīng)的RWPickFlavor.xcworkspace 中的分組,對所有的文件執(zhí)行拖拽并放開的操作 - 除了AppDelegate.swift 和LaunchScreen.xib,就像下面那樣:
如果有提示跳出,要保證Copy items if needed這個選項被確認過了,這樣所有的文件才是真正被拷貝而不是簡單地鏈接。當你完成以后,RWPickFlavor 應(yīng)該有下面的文件:
一旦你確定了所有的文件都已經(jīng)被拷貝過來了,從IceCreamShop中刪除所有的originals和任何空的分組,只剩下RWPickFlavor中的文件。小心不要刪除下面這些:
- AppDelegate.swift
- LaunchScreen.xib
- Images.xcassets
- Supporting Files 分組下的任何文件
現(xiàn)在打開Info.plist,在Supporting Files那個分組下,找到Main storyboard file base name那一行并刪除。
編譯運行,應(yīng)該不會有錯的,最終你會看到黑色的屏幕上顯示著 “Ice Cream Shop”的logo。
那么圖片呢?
你可能已經(jīng)注意到了你沒有拷貝Resources分組,這是因為你只需要拷貝background.jpg這個圖片本身到RWPickFlavor的Resources文件夾下,不是整個的Images.xcassets文件。
首先,你在RWPickFlavor中創(chuàng)建一個Resources分組。
然后,在IceCreamShop中選擇 Images.xcassets,選中background右擊并選擇Show in Finder,就像下面那樣:
現(xiàn)在把background.png從finder中拖拽到RMPickFlavor的resources分組中。當有彈出提示時,再次選中Copy items if needed選項。當你已經(jīng)拷貝了圖片,從IceCreamShop的Image.xcassets中刪除原始的background圖片。
最后,在Main.storyboard的Choose Your Flavor場景中的RMPickFlavor類里更新imageview的圖片,這樣他就指向了圖片background.jpg而不是background。
不管你信不信,創(chuàng)建你的pod的最困難的部分已經(jīng)完成了。
CocoaPods和Git
由于cocoapod是部署在git上面的, 每一個pod都需要有它自己的git目錄.如果你已經(jīng)有了git主機,你可以用它來放你的目錄。
如果沒有,Github是一個很不錯的選擇,因為它被眾多的開發(fā)者所了解并且對開源的項目免費。
Bitbucket是另外一個不錯的選擇,它是免費的并且沒有限制的,包括私有的目錄,可以供達5個開發(fā)人員共同開發(fā)。
這個教程使用了github,但是你也可以用你自己的git服務(wù)器。
GitHub目錄設(shè)置
下一步,點擊屏幕右上角的+(創(chuàng)建新的)圖標并且選擇下方的New repository.
輸入RMPickFlavor作為目錄名,并且選擇Create repository。
Github將在你的賬戶下面創(chuàng)建一個新的目錄,然后你將看到一個下面屏幕所示的Quick setup所展示的你的目錄URL:
你將在某一時刻需要這個URL,所以保持這個頁面打開。
現(xiàn)在你需要第二個目錄來放你的私有pod規(guī)范 - 之后你將在這篇教程中用到它。
在一個新的標簽頁中打開github.com;再次點擊Create New圖標并選擇New repository。將這個目錄取名為RWPodSpecs,并選擇Create repository。
保持這個標簽頁打開之后在你需要這個URL的時候你可以輕松獲取。
#p#
Podspec設(shè)置
現(xiàn)在你需要為RMPickFlavor創(chuàng)建一個RWPickFlavor.podspec文件。這個Podspec文件包含了一些基本的信息,比如pod的名字、版本和git下載URL.
在終端中輸入下面的命令行,在每一行輸入enter鍵。
- cd ~/Documents/Libraries/RWPickFlavor
- pod spec create RWPickFlavor
- open -a Xcode RWPickFlavor.podspec
這就創(chuàng)建了RWPickFlavor.podspec,在Xcode中打開。
在默認的podspec文件中有很多不錯的文檔和例子 - 然而,你不需要所有的這些。
用下面的內(nèi)容代替RWPickFlavor.podspec中的所有內(nèi)容
- # 1
- s.platform = :ios
- s.ios.deployment_target = '8.0'
- s.name = "RWPickFlavor"
- s.summary = "RWPickFlavor lets a user select an ice cream flavor."
- s.requires_arc = true
- # 2
- s.version = "0.1.0"
- # 3
- s.license = { :type => "MIT", :file => "LICENSE" }
- # 4 - Replace with your name and e-mail address
- s.author = { "[Your Name Goes Here]" => "[Your_Email@Your_Email_Domain.com]" }
- # For example,
- # s.author = { "Joshua Greene" => "jrg.developer@gmail.com" }
- # 5 - Replace this URL with your own Github page's URL (from the address bar)
- s.homepage = "[Your RWPickFlavor Homepage URL Goes Here]"
- # For example,
- # s.homepage = "https://github.com/JRG-Developer/RWPickFlavor"
- # 6 - Replace this URL with your own Git URL from "Quick Setup"
- s.source = { :git => "[Your RWPickFlavor Git URL Goes Here]", :tag => "#{s.version}"}
- # For example,
- # s.source = { :git => "https://github.com/JRG-Developer/RWPickFlavor.git", :tag => "#{s.version}"}
- # 7
- s.framework = "UIKit"
- s.dependency 'Alamofire', '~> 1.1'
- s.dependency 'MBProgressHUD', '~> 0.9.0'
- # 8
- s.source_files = "RWPickFlavor/**/*.{swift}"
- # 9
- s.resources = "RWPickFlavor/**/*.{png,jpeg,jpg,storyboard,xib}"
- end
正如podFile一樣,podspec也是用Ruby寫的。千萬小字不要出現(xiàn)打字錯誤,否則pod可能會出現(xiàn)確認或者安裝失敗的情況。
下面是正在進行的:
1.首先你要寫清楚pod的基本信息?;赟wift的cocppods的部署目標必須在iOS8.0及以上。如果你給了一個更低的版本,pod就不能正確安裝了。
2.podSpec實際上就是你的cocoapod的一個及時的截屏,并且用版本號來標記。當你更新一個pod,你也需要更新podspec的版本。所有的cocoapods都最好使用語義化版本號。如果你對Semantic Versioning不熟悉,請看How to Use CocoaPods with Swift
3.所有的pods都必須制定一個許可證。如果你沒有的話,當你視圖安裝的時候cocoapods會給你一個警告,并且你也不能把它上傳到cocoapods trunk---specs目錄下。
4.然后請寫明你自己的信息,這是pod的作者。在占位文字的地方輸入你的名字和e-mail地址。
5.現(xiàn)在你需要在你pod的主頁上寫明URL。你可以就從你的github主頁的瀏覽器的地址欄里面拷貝并粘貼地址。
6.將這個URL替換為上面你創(chuàng)建的第一個目錄中的“Quick Setup”部分的git下載URL。通常,最好是使用http:或者https:開頭的URL,這樣使用的人就更容易明白。你也可以使用SSHurl。但是你需要確認你的team中的所有人-無論是誰需要cocoapod的路徑-已經(jīng)有了配置你的git主機的公開/私密的鍵值對。
7.你要指明框架和任何pod依賴性文件。
8.你需要指明基于文件擴展的(public source files)公用資源文件。在這兒,你需要用.swift作為擴展。
9.最后,指明基于文件擴展的resources。
就像許多其他的pod,你需要創(chuàng)建LICENSE 文件。
復(fù)制這兒的MIT license在你最喜歡的編輯器中,然后保存為LICENSE到~/Documents/Libraries/RWPickFlavor目錄下,沒有擴展名。確保將[year]和[fullname]替換為真實值-啊,當然是你的真實的年份和名字了。
Choose a License是一個很棒的幫你的項目找到合適的開源license的一個站點,并且由hithub中的一些志愿者進行創(chuàng)建和維護。
上傳至Git
最后你準備將RMPickerFlavor上傳至git中的新家了。
在終端中輸入下面的命令行,將[Your RWPickFlavor Git URL]替換為你之前創(chuàng)建的RWPickFlavor目錄:
- cd ~/Documents/Libraries/RWPickFlavor
- git init
- git add .
- git commit -m "Initial commit"
- git tag 0.1.0
- git remote add origin [Your RWPickFlavor Git URL]
- git push -u origin master --tags
如果有彈出,輸入你的github的用戶名和密碼。
這就將RWPickFlavor文件夾中的所有文件都提交了,并創(chuàng)建了一個0.1.0的tag,并且把所有的東西上傳到遠程目錄中。
恭喜你,你已經(jīng)創(chuàng)建了你的第一個cocoapod!
你已經(jīng)創(chuàng)建了你的第一個cocoapod,但是你能使用它嗎?是的,還不一定:
首先你需要將你的podspec添加到一個私人的specs目錄下;這樣當你安裝的時候cocoapods就能找到pod了。幸運的,你已經(jīng)為此創(chuàng)建了一個git目錄,所以這最后的一步是相對簡單明了的。
輸入下面的命令,要確保你還在 RWPickFlavor 目錄下:
- pod repo add RWPodSpecs [Your RWPodSpecs Git URL]
- pod repo push RWPodSpecs RWPickFlavor.podspec
要確保你已經(jīng)用之前創(chuàng)建的RWPodSpecs 目錄對應(yīng)的git url替換了[Your RWPodSpecs Git URL]
這就在你本地電腦上創(chuàng)建了RWPodSpecs的一個本地參考并且保存在你的電腦的~/.cocoapods目錄下,將RWPickFlavor.podspec上傳到那里。
需要你有了一個私人的pod規(guī)范目錄。比你想的要容易,對吧?
使用你的新CocoaPod
這是使用你的新創(chuàng)建的pod的最后時刻了。
打開IceCreamShop的podfile并且用下面的命令替換它的內(nèi)容
platform :ios, '8.0'
- source 'https://github.com/CocoaPods/Specs.git'
- source '[Your RWPodSpecs Git URL Goes Here]'
- use_frameworks!
- target 'IceCreamShop' do
- pod 'RWPickFlavor', :path => '~/Documents/Libraries/RWPickFlavor'
- end
確保你已經(jīng)用你的RWPodSpecs目錄對應(yīng)的gitURL替換了[Your RWPodSpecs Git URL Goes Here]
然后,在終端中運行pod install。
最后,用下面的命令替換AppDelegate.swift中的所有內(nèi)容
- import UIKit
- import RWPickFlavor
- @UIApplicationMain
- class AppDelegate: UIResponder, UIApplicationDelegate {
- var window: UIWindow?
- var rootViewController: UIViewController!
- func application(application: UIApplication, didFinishLaunchingWithOptions
- launchOptions: [NSObject : AnyObject]?) -> Bool {
- setupRootViewController()
- window = UIWindow(frame: UIScreen.mainScreen().bounds)
- window?.rootViewController = rootViewController
- window?.makeKeyAndVisible()
- return true
- }
- func setupRootViewController() {
- let bundle = NSBundle(forClass: PickFlavorViewController.self)
- let storyboard = UIStoryboard(name: "Main", bundle: bundle)
- rootViewController = storyboard.instantiateInitialViewController() as! UIViewController
- }
- }
在setupRootViewController()中,你獲取了對RWPickFlavor包內(nèi)容的參考 ---它其實是一個動態(tài)的框架--這個方法創(chuàng)建了Main.storyboard,并且初始化了根視圖
編譯運行??吹绞煜さ?ldquo;Choose Your Flavour”你肯定會很開心。太棒了!
抽象所有的東西!
你如果像我這樣,你可能會想,“哇,app Delegate 肯定對RWPickFlavor的結(jié)構(gòu)影響很多”。
幸運的是,你可以做一些事來降低耦合度:使用BetterBaseClasses,這是一個可以使其他pods使用更方便的pod。
在RWPickFlavor的pod文件中添加下面的代碼,就在Alamofire的后面:
- pod 'BetterBaseClasses', '~> 1.0'
同樣地,將下面的命令添加到RWPickFlavor.podspec,在Alamofire那一行的下面:
- s.dependency 'BetterBaseClasses', '~> 1.0'
現(xiàn)在用下面的內(nèi)容替換s.version
- s.version = "0.2.0"
現(xiàn)在你要將BetterBaseClasses聲明為一個依賴,然后and then bumping the version of your CocoaPod.
現(xiàn)在在終端中運行pod install來安裝新的依賴性文件。
接下來,將下面的內(nèi)容導(dǎo)入到PickFlavorViewController中,還是在Alamofire的后面:
- import BetterBaseClasses
用下面的內(nèi)容替換類的定義:
- public class PickFlavorViewController: BaseViewController, UICollectionViewDelegate {
這就改變了PickFlavorViewController而使它繼承自BaseViewController,BaseViewController是BetterBaseClasses的一部分。
現(xiàn)在你需要將這些改變推送到你的RWPickFlavor和RWPodSpecs目錄下。在終端中運行下面的命令:
- cd ~/Documents/Libraries/RWPickFlavor
- git add .
- git commit -m "Added BetterBaseClasses dependency"
- git tag 0.2.0
- git push origin master --tags
- pod repo push RWPodSpecs RWPickFlavor.podspec
接下來,你需要將這些改變拉取到IceCreamShop中。
更新IceCreamShop的PodFile,用下面的代碼替換pod 'RWPickFlavor'.
- pod 'RWPickFlavor', '~> 0.2.0'
下面你將更新PodFile來獲取你剛剛上傳的RWPickerFlavor的新版本。然后在終端中執(zhí)行pod install在IceCreamShop中跟新新的依賴。
最后,用下面的內(nèi)容替換AppDelegate.swift中的全部內(nèi)容:
- import UIKit
- import RWPickFlavor
- @UIApplicationMain
- class AppDelegate: UIResponder, UIApplicationDelegate {
- var window: UIWindow?
- func application(application: UIApplication, didFinishLaunchingWithOptions
- launchOptions: [NSObject : AnyObject]?) -> Bool {
- window = UIWindow(frame: UIScreen.mainScreen().bounds)
- window?.rootViewController = UINavigationController(rootViewController:
- PickFlavorViewController.instanceFromStoryboard())
- window?.makeKeyAndVisible()
- return true
- }
- }
那就簡單得多了!
BetterBaseClasses在UIViewController,UITableViewController以及其他UIKit類中添加分類。其中包含了一個叫UIViewController+BetterBaseClasses的分類,這個分類添加了一些很方便的方法比如 instanceFromStoryboard()使初始化ViewControllers非常簡單,不管它們是在main bundle或者是別的什么地方,就像這個例子中的框架一樣。
編譯運行,這一次,你會看到熟悉的‘ Choose Your Flavor’。
接下來?
你可以在 這兒 下載到完整的IceCreamShop項目,以及RWPickFlavor pod。
現(xiàn)在你可以開始創(chuàng)建你自己的CocoaPods了!不過,你在這篇教程中學(xué)到的只是在涉及到cocoapod時的一小部分建議。請下載CocoaPods 指南來學(xué)習(xí)關(guān)于創(chuàng)建cocoapods的所有的內(nèi)容
在你創(chuàng)建了cocoapod之后,你可能會考慮將它添加到CocoaPods Master Specs Repo中,這樣全世界的開發(fā)者就可以通過CocoaPods.org獲取d熬它了。你可以看看這篇博客來學(xué)習(xí)怎么做CocoaPods Trunk。