CocoaPods: What is it Good For?
Not absolutely nothing, that’s for sure.
Before we look at why you would want to use CocoaPods and how to use it, we should look at what it is.
CocoaPods is a dependency management tool for iOS and OS X development that has been gaining a lot of traction in the Cocoa community. When using CocoaPods, you define your project’s dependencies in a file, which CocoaPods uses to determine and resolve dependencies between libraries before downloading the needed source code and linking it in an Xcode workspace.
Why Use CocoaPods?
I’ll start with a hypothetical scenario.
You begin working on a project and everything is going great (It could be a solo project or a team project). As the project progresses, you find it necessary to use third party libraries to help the project move along faster (the whole ‘do not reinvent the wheel’ thing). You do this by searching for appropriate libraries and copying the source code into your project.
You star the projects repositories on Github (or wherever they are hosted) to keep track of updates. When a library is updated, you manually update it in your project. At times, a library might break your build, forcing you to revert back to a compatible version. You have to search for it and copy it into your project. Add more libraries and you start noticing the time drain that maintaining your project dependencies is.
You are also bound to encounter situations where a library you want to use depends on another library and you will have to get them both. If you use multiple libraries sharing a dependency, but all specify a different version of the dependency, you’ll have to figure out what the best version of the library is that will satisfy all dependencies.
As your project scales, you’ll be spending a lot of time managing its dependencies, time that could be better used writing code.
CocoaPods make managing dependencies in your code easier. Adding and removing dependencies is just a matter of defining them in a file and running a command to install them. CocoaPods reads the file, determines the dependencies that the listed libraries have and if there are any shared dependencies, it tries to determine the version that will satisfy all of them. It uses Semantic Versioning to try to resolve dependency versions.
For instance, if two different pods depend on different versions of a library, e.g. 1.1.1 and 1.1.2, CocoaPods might pick the newer version 1.1.2 since patch versions are usually backward compatible. You can read more on that here. Automatic resolution doesn’t always happen though. Usually CocoaPods notifies you of the conflict, and you have to specify the version of the conflicting pod. But the CocoaPods team say that automatic conflict resolution is on their ToDo list.
Getting a specific version of a pod is done by specifying the version number, and CocoaPods downloads that specific version for you saving you from searching through commits for it.
With CocoaPods, updating your dependancies is easily done with the
pod update command.
CocoaPods also provides a central place where third party libraries can be found. This improves discoverability of open source libraries that you can use in your projects. You can use the search engine at cocoapods.org to search for pods.
Another advantage of CocoaPods is that it generates an acknowledgement file with the licence information of all the pods you are using. Without this, you would need to copy the licence documents of all the open source libraries you are using and put them together somewhere on your project.
CocoaPods is distributed as a Ruby gem and so will require Ruby and RubyGems (the Ruby package manager) to be installed on your system. Recent versions of Mac OS X come with Ruby installed, so you probably won’t need to install it. You can also use a Ruby version manager like RVM to install Ruby on your system.
To check whether Ruby is installed, run the
ruby -v command in the Terminal. That should give you the Ruby version number, and if it isn’t installed, you will get an error message saying that there is no such command. Since version 1.9, Ruby comes with RubyGems by default.
Before installing CocoaPods, first update your RubyGems.
[sudo] gem update --system
To install CocoaPods, run the following command.
[sudo] gem install cocoapods
For both the commands above, the
sudo command is optional and depends on which Ruby installation you are using. If you are using the default system provided Ruby installation, then you will require root privileges to install gems and thus you will need to include the sudo command. If you are using a Ruby version manager like RVM or rbenv, this will not be required and you can just run
gem install cocoapods.
During installation, you might get a warning asking if you want to overwrite the rake executable. This is due to the rake gem being updated in the process, so confirm the overwrite by typing
Whenever you need to update CocoaPods, run the same command you used to install it.
Next run the following to setup CocoaPods on you system.
This will create a
~/.cocoapods/ directory which will contain all the available public pod specifications cloned from the CocoaPods Master Specs Repo.
Now we are all set up and ready to use CocoaPods in our project.
Using CocoaPods in a Project
We will create a simple project to demonstrate how to use CocoaPods. I have created a simple application called TestApp. It is an iPhone Single View Application. I will include a pod that formats numbers.
You can search for pods at the CocoaPods website. I searched for ‘Formatter’ and got several results for number formatters, address formatters, phone formatters etc. The list of results includes links to each pod’s site, documentation and spec file.
I will use the AKNumericFormatter library.
To define dependancies for your project, you create a Podfile and list all the libraries you want to use with an optional version number.
To create the Podfile, using Terminal, navigate to the root of the app you created.
Run the following command, which will create a Podfile at the specified file path.
Podfile just created in a text editor. It will have some default code. You can specify the pods you want to use in each target.
# Uncomment this line to define a global platform for your project # platform :ios, "6.0" target "TestApp" do end target "TestAppTests" do end
Uncomment the statement that specifies your project’s target and edit the version number. The platform can be either
platform :ios, "7.0"
Inside the TestApp target block add, the following.
When the version number is not specified as in the example above, the latest version of the pod will be fetched.
You can specify an exact version by including a specific version number. For instance,
pod 'AFNetworking', '1.0'
Logical operators can also be used, e.g. ‘> 0.1’, ‘>= 0.1’, ‘< 0.1’, ‘<= 0.1’.
The pessimistic operator
~> can also be used to control the allowed updates. For example with
~> 0.1.2 you’ll get the highest released version of the pod between v0.1.2 and v0.2, not including 0.2.
You might be tempted to leave all the pods’ versions in your Podfile unspecified so that when you update, the latest version is fetched, but this might not be a good idea. You could upgrade to a major version change that could have new features and API changes that no longer work with your code. It might be better to freeze a pod to a specific version or to only allow minor version updates. CocoaPods follows the Semantic Versioning policy. You can read more about major, minor and patch versions at the given link.
It is also possible to use a pod on your local machine.
pod 'ExamplePod', :path => '~/Documents/ExamplePod'
Or from a git repository. Mercurial and SVN are also supported.
pod 'ExamplePod', :git => 'https://github.com/eguser/ExamplePod.git', :branch => 'dev'
Back to our example, after editing the Podfile, save it and run the following command.
CocoaPods will analyze the dependancies listed in the Podfile and download the libraries into a new project named Pods, which is placed in a created Xcode workspace named TestApp.xcworkspace. You will receive a message in the Terminal telling you to use the new workspace.
If you had your project open in Xcode, close it and open the workspace instead. If you try to run the old project, it won’t build. You will receive a linking error message.
The workspace will have two projects – your project (TestApp) and the Pods project. In the Pods project is a group folder with your downloaded pods. You can now use the libraries in your app. Remember to add the import before calling any of the framework’s methods.
To remove a pod from your project, remove it from the Podfile and run
pod install. Same goes for adding a new pod.
To update your project’s dependencies, run
CocoaPods and Source Control
There are various arguments on what CocoaPods files should go under version control. This is simply a matter of preference. There is a list of pros and cons of adding the Pods folder in your
.gitignore file. You should however keep the Podfile.lock under version control. This is the file that keeps track of what version of a Pod is installed.
Trying Out Pods
CocoaPods has a feature that enables you to download and try out a library before you use it in your project. It downloads the demo project of a Pod and opens it in Xcode.
pod try [LIB_NAME] command to try out a Pod.
pod try AFNetworking
CocoaPods is a tool that makes managing your project much simpler. It can save you a lot of effort and time when dealing with dependencies in your project as it makes adding, removing and updating libraries that much easier. For more on using and troubleshooting CocoaPods, check out the CocoaPods guides.