We're Cuckoo for Cocoapods!

Posted on by Joseph Lorich

When we first started iOS development here at Cloudspace we found managing libraries in Objective-C to be extremely inconvenient. Organizing and maintaining the application code, along with all the shared libraries we've written, and a bunch of third party code (not to mention all their dependencies) wound up consuming quite a bit of time. Since we frequently work with Ruby, we've been spoiled with Gems. Our work in Objective-C felt a bit sluggish in comparison, so we set out to find a way to apply the same basic concept of RubyGems to our iOS projects.

Cuckoo for CocoaPods

After a few months of managing everything by hand we stumbled upon Cocoapods and were blown away. I don't know how it remained hidden from us for so long, but it's hands down one of the most useful iOS/OS X development tools there is. Written in Ruby (which we love), Cocoapods is a command line tool that handles basically all your library and dependency management. It's modeled after Gems/Bundler and works very similarly. Simply define a podfile in your project directory, listing all your libraries, and run pod install. It will build a new Xcode workspace file that includes your project along with a Pods project containing all the libraries you requested and dependencies needed. Simply open this workspace instead of your project, include the new libraries in your headers, and suddenly hours of organizing code, managing dependencies, debugging missing linked libraries, and handling updates is all just done for you.

Podfiles


For a great basic example, here is the podfile for one of our soon to be released open source apps, Easy Reader (an RSS feed reader/manager).

platform :ios, '6.0'

# Cocopods public repository
pod 'SDWebImage', '~> 3.2'
pod 'MBProgressHUD', '~> 0.6'
pod 'MFSideMenu', '~> 0.4.8'
pod 'TestFlightSDK', '~> 1.3.0beta2'
pod 'MagicalRecord', '~> 2.1.0'
pod 'SVPullToRefresh'
pod 'AFNetworking', '~> 1.2.0'

# Cloudspace private repository
pod 'CSEnhancedTableView', '~> 0.0.1'
pod 'CSStandardViewControllers', '~> 0.0.1'
pod 'CSShortcuts', '~> 0.0.1'

At the top we define the platform we're compiling to. This doesn't actually overwrite compiler settings, but it will check all that all the libraries you've chosen are compatible.

Next we have the pods (libraries) we want in our project. At Cloudspace we have our own private set of pods that we use in addition to the common public pods, so I like to keep them listed separately. When pod install is run, each of the listed libraries (and their dependencies) will be added to the Pods project at the requested version. In many of the cases above we use ~> before the versions, this means Cocoapods will install the latest minor revision of a library with the listed version being the minimum allowed. You can also use >= to get the newest version after what was listed, or just not list a version to always get the latest available (this isn't advised unless there are no version numbers available as you don't know what you'll get).

Podspecs - Revision Control at Heart


Unlike Ruby's Gems, instead of using a single host (e.g. rubygems.org) Cocoapods always references external code repositories (generally that of the original author). It offers support for referencing git, subversion, and mercurial repositories (should you have them installed). This does have the downside of the possibility of something happening to the repo, but allows for extreme flexibility as you can create your own pods very quickly (we'll go over that later) or even make pods to reference code managed by someone else with hardly any effort at all.

Each Pod that's available to install is defined by a podspec file (see the podspec spec here). There is a public collection of podspecs maintained by Cocoapods and stored in a GitHub repository (This public repo doesn't contain any actual code, just the specs). This repo is included in Cocoapods by default, though you can add your own too. podspec files contain information about the library, it's author, copyright, license, etc, as well as the supported platforms, versions, needed dependencies, and source locations.

Below is an example podspec out of the public repo for ABContactHelper version 0.0.1 (a great Address Book API wrapper library by Erica Sadun):

Pod::Spec.new do |s|
  s.name     = 'ABContactHelper'
  s.version  = '0.0.1'
  s.license  = 'BSD'
  s.summary  = 'Objective-C Address Book wrapper.'
  s.homepage = 'https://github.com/erica/ABContactHelper'
  s.author   = { 'Erica Sadun' => '' }
  s.source   = { :git => 'https://github.com/erica/ABContactHelper.git', :commit => 'de4bc411fd45db5e7b5b13f38704764bc1e1bcd1' }
  s.platform = :ios
  s.source_files = 'ABContact.{h,m}', 'ABGroup.{h,m}', 'ABContactsHelper.{h,m}'
  s.frameworks = 'AddressBook', 'AddressBookUI'
end

Here you can see all the available metadata (which is both nice to know, and used to populate the search on cocoapods.org) as well as the listed source (which specifies a specific git commit for this version) and platform. It also defines which files out of the source repository are necessary and which Apple frameworks need to be included to make it all work.

When pod install is run the podspecs for each version of each pod are parsed, verified against your listed platform/version, and added to your application workspace. Since Cocoapods is git based, with the main repository held on github, it is possible for your podspecs to get out of date. You can easily update them to the newest version by running pod repo update.

Pods for Private Libraries


Not every piece of code written is intended to be for the public (unless maybe you're RMS), so submitting podspecs for your own libraries to the main public repo just isn't always an option. Thankfully, you can add your own podspec repositories to Cocoapods with the following command:

pod repo add my-spec-repo http://github.com/my-account/spec-repo.git

Since Cocoapods uses git and all the git settings on your machine, support for accessing private repos with ssh-key access is automatic. If you don't use ssh keys and you have a private repo you may have some issues having to type your password over and over. To stay sane we highly recommend adding keys from your dev machine to your github account.

The repo layout is quite simple. Simply create folders with the name of each pod, then subfolders with the respective release version numbers, and then a single file inside each of those folders with the name [your pod name].podspec. For some great examples take a look through the public Cocoapods spec repo.

Once you've got your repo set up and added to Cocoapods you can use your own pods in your podfile and pod install. A private podspec repo allows you to easily managed shared internal libraries amongst multiple people and projects and can prevent many headaches.

<3<3<3


Overall, we love Cocoapods! It's an amazing tool that lets us build projects in a more efficient and reliable manner, saving us time and our clients money. We've used it on a number of projects and definitely will to continue to in the future. If you're a fellow developer looking to start using Cocoapods definitely check out Ray Wenderlich's Cocoapods tutorial. It's incredibly detailed and walks you through every step of the way.

Have a question about Cocoapods that you didn't see covered here? Let us know, and we'll get on it in two shakes of a lambs tail!

 
comments powered by Disqus