本文由yake_099(博客)翻译自raywenderlich,作者:Joshua Greene

原文:How to Create CocoaPods with Swift


你可能对一些比较著名的开源的CocoaPods框架比较熟悉,比如AlamofireMBProgressHUD。但是有时你可能找不到刚好满足你需求的pod,也或者你需要把一个大的项目拆分成小的,可重用的组件。

幸运的是,创建你自己的CocoaPods是件很容易的事!

如果你已经为你的组件创建了一个Cocoa Touch框架,你已经完成了大多数的比较难的工作。如果你没有也不要害怕,因为它还是很简单的。

如果你只是曾经创建过iOS app的类的话,那也是可以的。你可以简单地通过拖拽类或者方法来创建新的pod,这对你专属的使用会很有意义。

这篇教程是开端,How to Use CocoaPods with Swift(中文 英文是结束。如果你之前从没用过cocoaPods,那么这篇文章绝对是你学习的前提。

因此,来一杯热可可开始学习吧!

开始

你的首要客户是冰淇淋公司。他们的冰淇淋太受欢迎了以至于不能在柜台接收用户订单了。他们雇佣你来做一个漂亮的iOS应用,那样就能让用户在他们的iPhone上下订单了。你开始开发app了,并且进展得还不错。

在这里下载开始程序-------这是教程 How to Use CocoaPods with Swift(中文 英文)里的最终版本。

app已经有几个pod依赖文件在下载中,所以你不需要运行pod install来安装它们。

注意:如果你已经学习了 How to Use CocoaPods with Swift中文 英文,那么接下来的部分看起来可能比较熟悉----只是对那篇教程的复习。所以可以根据自己的情况跳过一部分。打开 IceCreamShop.xcworkspace,然后是Main.storyboard,找到Views\Storyboards & Nibs这个分组,看看app是怎样布局的。

下面是对选择口味场景的一个大致了解,这是这个应用的核心:

  • PickFlavorViewController: 处理用户交互,比如用户选择了一个冰淇淋口味。

  • PickFlavorDataSource: 是展示冰淇淋口味的collectionview的数据源。

  • IceCreamView:是一个自定义的view,可以用来展示一种冰淇淋,并且它以Falvor这个模型来支撑。

  • ScoopCell:是一个自定义的collectionviewcell,它包含了一个ScoopView,这个view也是以Flavor这个model类来支撑的。

storyboard_annotated-427x500.png

冰淇淋店的高层管理者很喜欢现在的app,但是他们又添加了一些新的需求:冰淇淋零售商需要在他们的app中有选择个人口味的功能。等等,那没有在最初的设计中。但是对于像你这样厉害的开发者这没有问题!

SuperDev.jpg

你能猜到怎么做吗?是的,你需要在他自己的cocoapod中拉入这个方法。

配置你自己的pod

创建一个Xcode工程并且选择iOS\Framework & Library\Cocoa TouchFramework,然后点击下一步

cocoapod1.png

输入RWPickFlavor作为产品名字并且选择Swift作为开发语言。选择下一步。

这篇教程需要你将你的工程创建在~/Documents/Libraries目录下.在你的主目录下选择Documents文件夹。如果你没有Libraries文件夹,在底部点击New Folder按钮并且创建它。

最后,选择Libraries文件夹并且点击创建。

你保存你的pod的目录是很重要的因为在本地开发期间你需要在podFile中参考你的目录。

通常,当你使用CocoaPods,你会像下面那样将依赖性文件加入你的Podfile中

1
pod  'PodName' '~> 1.0'

但是当你在开发自己的CocoaPod,你却需要指明一个本地的路径,就像这样:

1
pod  'MyPodName' , :path =>  '~/Path/To/Folder/Containing/My/Pod'

这种方法有两个好处:

1.它会使用在你电脑上的对应的pod的本地文件,而不用从远端目录下抓取。

2.通常,你不会修改加入到你的app中的pod,因为这些修改会在下次你运行pod install的时候被覆盖掉,因为pod会从远端目录下重新获取并且你修改的资源文件也会被覆盖。通过使用:path => syntax,你可以轻松地修改开发中的pod而不会被这个过程覆盖,因为那个路径就是现在CocoaPod的来源,因此当你再次运行pod install的时候这些修改不会丢失。

然而你可以为你在开发的pods使用不同的路径,一般我建议将他们放在~/Documents/Libraries下。如果你有一个团队在开发的话这也是一个很好的位置,因为cocoapods知道把“~”扩展为用户的目录。因此你不需要在podFile中写很复杂的代码来表示绝对路径。

你也可以在你创建的cocoapod中引用其他的cocoapod作为依赖性文件-你只需要一个podFile来管理你的cocoaPods依赖性文件。

关闭Xcode,然后在终端中输入下面的命令行:

1
2
3
cd ~/Documents/Libraries/RWPickFlavor
pod init
open -a Xcode Podfile

这就创建了一个新的podFile并且在Xcode中打开它。

用下面的内容替换新的podFile中的内容:

1
2
3
4
5
6
platform :ios,  '8.0'
use_frameworks!
target  'RWPickFlavor'  do
  pod  'Alamofire' '~> 1.2'
  pod  'MBProgressHUD' '~> 0.9.0'
end

这就声明了RWPickerFlavor有外部依赖性文件Alamofire和MBProgressHUD。

保存并且关闭podFile,然后在终端中输入下面的命令行:

1
pod install

正如你希望的那样,这就会创建一个workspace并且安装各种必需的文件

注意:如果pod install命令给出了任何警告,那么你有可能用的是一个老版本的Cocoapods。基于swift语言的cocoapods,例如Alamofire,要求cocoapods版本在0.36.0及以上。你可以尝试在终端中输入以下命令来查看你的cocoapods版本:

1
pod --version

如果是那个问题的话,在终端中输入如下命令来安装cocoapods的最新版本:

1
sudo gem install CocoaPods

输入以下命令行打开新创建的RWPickFlavor workspace:

1
open RWPickflavor.xcworkspace

你的项目导航栏现在看起来应该是这样的:

cocoapod2.png

现在你需要将 IceCreamShop workspace中的几个文件拷贝到RWPickFlavor中。

首先,在 RWPickFlavor.xcworkspace 中创建下面的分组来归类你将要拷贝的文件:

  • Categories

  • Controllers

  • Factories

  • Models

  • Views(Ice Cream,Storyboards & Nibs

IceCreamShop.xcworkspace中的分组到对应的RWPickFlavor.xcworkspace 中的分组,对所有的文件执行拖拽并放开的操作 - 除了AppDelegate.swift 和LaunchScreen.xib,就像下面那样:

cocoapod3.gif

如果有提示跳出,要保证Copy items if needed这个选项被确认过了,这样所有的文件才是真正被拷贝而不是简单地链接。当你完成以后,RWPickFlavor 应该有下面的文件:

25.png

一旦你确定了所有的文件都已经被拷贝过来了,从IceCreamShop中删除所有的originals和任何空的分组,只剩下RWPickFlavor中的文件。小心不要删除下面这些:

  • AppDelegate.swift

  • LaunchScreen.xib

  • Images.xcassets

  • Supporting Files 分组下的任何文件

现在打开Info.plist,在Supporting Files那个分组下,找到Main storyboard file base name那一行并删除。

编译运行,应该不会有错的,最终你会看到黑色的屏幕上显示着 “Ice Cream Shop”的logo。

那么图片呢?

你可能已经注意到了你没有拷贝Resources分组,这是因为你只需要拷贝background.jpg这个图片本身到RWPickFlavor的Resources文件夹下,不是整个的Images.xcassets文件。

首先,你在RWPickFlavor中创建一个Resources分组。

然后,在IceCreamShop中选择 Images.xcassets,选中background右击并选择Show in Finder,就像下面那样:

cocoapod4.png

现在把background.pngfinder中拖拽到RMPickFlavorresources分组中。当有弹出提示时,再次选中Copy items if needed选项。当你已经拷贝了图片,从IceCreamShopImage.xcassets中删除原始的background图片。

最后,在Main.storyboardChoose Your Flavor场景中的RMPickFlavor类里更新imageview的图片,这样他就指向了图片background.jpg而不是background

cocoapod5.png

不管你信不信,创建你的pod的最困难的部分已经完成了。

high_five_kitten-349x500.jpg

CocoaPods和Git

由于cocoapod是部署在git上面的, 每一个pod都需要有它自己的git目录.如果你已经有了git主机,你可以用它来放你的目录。

如果没有,Github是一个很不错的选择,因为它被众多的开发者所了解并且对开源的项目免费。

Bitbucket是另外一个不错的选择,它是免费的并且没有限制的,包括私有的目录,可以供达5个开发人员共同开发。

这个教程使用了github,但是你也可以用你自己的git服务器。

GitHub目录设置

首先,注册登陆你的github账号。

下一步,点击屏幕右上角的+(创建新的)图标并且选择下方的New repository.

github_new_repository-480x152.png

输入RMPickFlavor作为目录名,并且选择Create repository

Github将在你的账户下面创建一个新的目录,然后你将看到一个下面屏幕所示的Quick setup所展示的你的目录URL:

github_quick_setup-480x56.png

你将在某一时刻需要这个URL,所以保持这个页面打开。

现在你需要第二个目录来放你的私有pod规范 - 之后你将在这篇教程中用到它。

在一个新的标签页中打开github.com;再次点击Create New图标并选择New repository。将这个目录取名为RWPodSpecs,并选择Create repository

保持这个标签页打开之后在你需要这个URL的时候你可以轻松获取。

Podspec设置

现在你需要为RMPickFlavor创建一个RWPickFlavor.podspec文件。这个Podspec文件包含了一些基本的信息,比如pod的名字、版本和git下载URL.

在终端中输入下面的命令行,在每一行输入enter键。

1
2
3
cd ~/Documents/Libraries/RWPickFlavor
pod spec create RWPickFlavor
open -a Xcode RWPickFlavor.podspec

这就创建了RWPickFlavor.podspec,在Xcode中打开。

在默认的podspec文件中有很多不错的文档和例子 - 然而,你不需要所有的这些。

用下面的内容代替RWPickFlavor.podspec中的所有内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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,
  # 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写的。千万小字不要出现打字错误,否则pod可能会出现确认或者安装失败的情况。

下面是正在进行的:

1.首先你要写清楚pod的基本信息。基于Swift的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.现在你需要在你pod的主页上写明URL。你可以就从你的github主页的浏览器的地址栏里面拷贝并粘贴地址。

6.将这个URL替换为上面你创建的第一个目录中的“Quick Setup”部分的git下载URL。通常,最好是使用http:或者https:开头的URL,这样使用的人就更容易明白。你也可以使用SSHurl。但是你需要确认你的team中的所有人-无论是谁需要cocoapod的路径-已经有了配置你的git主机的公开/私密的键值对。

7.你要指明框架和任何pod依赖性文件。

8.你需要指明基于文件扩展的(public source files)公用资源文件。在这儿,你需要用.swift作为扩展。

9.最后,指明基于文件扩展的resources。

就像许多其他的pod,你需要创建LICENSE 文件。

复制这儿的MIT license在你最喜欢的编辑器中,然后保存为LICENSE到~/Documents/Libraries/RWPickFlavor目录下,没有扩展名。确保将[year][fullname]替换为真实值-啊,当然是你的真实的年份和名字了。

Choose a License是一个很棒的帮你的项目找到合适的开源license的一个站点,并且由hithub中的一些志愿者进行创建和维护。

上传至Git

最后你准备将RMPickerFlavor上传至git中的新家了。

在终端中输入下面的命令行,将[Your RWPickFlavor Git URL]替换为你之前创建的RWPickFlavor目录:

1
2
3
4
5
6
7
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文件夹中的所有文件都提交了,并创建了一个0.1.0的tag,并且把所有的东西上传到远程目录中。

恭喜你,你已经创建了你的第一个cocoapod!

victory_dance-417x320.png

你已经创建了你的第一个cocoapod,但是你能使用它吗?是的,还不一定:

首先你需要将你的podspec添加到一个私人的specs目录下;这样当你安装的时候cocoapods就能找到pod了。幸运的,你已经为此创建了一个git目录,所以这最后的一步是相对简单明了的。

输入下面的命令,要确保你还在 RWPickFlavor 目录下:

1
2
pod repo add RWPodSpecs [Your RWPodSpecs Git URL]
pod repo push RWPodSpecs RWPickFlavor.podspec

要确保你已经用之前创建的RWPodSpecs 目录对应的git url替换了[Your RWPodSpecs Git URL] 

这就在你本地电脑上创建了RWPodSpecs的一个本地参考并且保存在你的电脑的~/.cocoapods目录下,将RWPickFlavor.podspec上传到那里。

需要你有了一个私人的pod规范目录。比你想的要容易,对吧?

使用你的新CocoaPod

这是使用你的新创建的pod的最后时刻了。

打开IceCreamShop的podfile并且用下面的命令替换它的内容

platform :ios, '8.0'

1
2
3
4
5
6
source  '[Your RWPodSpecs Git URL Goes Here]'
use_frameworks!
target  'IceCreamShop'  do
  pod  'RWPickFlavor' , :path =>  '~/Documents/Libraries/RWPickFlavor'
end

确保你已经用你的RWPodSpecs目录对应的gitURL替换了[Your RWPodSpecs Git URL Goes Here]

然后,在终端中运行pod install

最后,用下面的命令替换AppDelegate.swift中的所有内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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包内容的参考 ---它其实是一个动态的框架--这个方法创建了Main.storyboard,并且初始化了根视图

编译运行。看到熟悉的“Choose Your Flavour”你肯定会很开心。太棒了!

choose_flavor-180x320.png

抽象所有的东西!

你如果像我这样,你可能会想,“哇,app Delegate 肯定对RWPickFlavor的结构影响很多”。

幸运的是,你可以做一些事来降低耦合度:使用BetterBaseClasses,这是一个可以使其他pods使用更方便的pod。

RWPickFlavor的pod文件中添加下面的代码,就在Alamofire的后面:

1
pod  'BetterBaseClasses' '~> 1.0'

同样地,将下面的命令添加到RWPickFlavor.podspec,在Alamofire那一行的下面:

1
s.dependency  'BetterBaseClasses' '~> 1.0'

现在用下面的内容替换s.version

1
s.version =  "0.2.0"

现在你要将BetterBaseClasses声明为一个依赖,然后and then bumping the version of your CocoaPod.

现在在终端中运行pod install来安装新的依赖性文件。

接下来,将下面的内容导入到PickFlavorViewController中,还是在Alamofire的后面:

1
import BetterBaseClasses

用下面的内容替换类的定义:

1
public class PickFlavorViewController: BaseViewController, UICollectionViewDelegate {

这就改变了PickFlavorViewController而使它继承自BaseViewController,BaseViewControllerBetterBaseClasses的一部分。

现在你需要将这些改变推送到你的RWPickFlavor和RWPodSpecs目录下。在终端中运行下面的命令:

1
2
3
4
5
6
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中。

更新IceCreamShopPodFile,用下面的代码替换pod 'RWPickFlavor'.

1
pod  'RWPickFlavor' '~> 0.2.0'

下面你将更新PodFile来获取你刚刚上传的RWPickerFlavor的新版本。然后在终端中执行pod installIceCreamShop中跟新新的依赖。

最后,用下面的内容替换AppDelegate.swift中的全部内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
  }
}

那就简单得多了!

BetterBaseClassesUIViewController,UITableViewController以及其他UIKit类中添加分类。其中包含了一个叫UIViewController+BetterBaseClasses的分类,这个分类添加了一些很方便的方法比如 instanceFromStoryboard()使初始化ViewControllers非常简单,不管它们是在main bundle或者是别的什么地方,就像这个例子中的框架一样。

编译运行,这一次,你会看到熟悉的‘ Choose Your Flavor’

接下来?

你可以在 这儿 下载到完整的IceCreamShop项目,以及RWPickFlavor pod

现在你可以开始创建你自己的CocoaPods了!不过,你在这篇教程中学到的只是在涉及到cocoapod时的一小部分建议。请下载CocoaPods 指南来学习关于创建cocoapods的所有的内容

在你创建了cocoapod之后,你可能会考虑将它添加到CocoaPods Master Specs Repo中,这样全世界的开发者就可以通过CocoaPods.org获取d熬它了。你可以看看这篇博客来学习怎么做CocoaPods Trunk


转载于:https://my.oschina.net/hejunbinlan/blog/488779

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐