In the world of dependency management, every platform has their own solutions. Up until recently there hasn’t really been a good solution in Objective-C. CocoaPods is a relatively newish dependency management system for Objective-C. I’ve seen it mentioned in a few GitHub projects over the years, and recently I decided to try it out. At the time of this post they’re on version 0.33, but despite not being to a 1.0 release, it works really well.
Installation
CocoaPods installation is quite simple thanks to it being a Ruby Gem. If you’re running the latest version of Xcode (5.1.X) an OS X (Mavericks), you’ll just need to run the following command:
1 |
sudo ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future gem install cocoapods |
That will install the pod command, which virtually everything for CocoaPods runs through.
When using CocoaPods, you’ll be editing a lot of *.podspec and “Podfile” files. There is no real IDE integration for CocoaPods. If you’re using Alcatraz as an Xcode plugin manager, there is a plugin to give you some CocoaPods integration. I’ve had mixed experience with the plugin. I find it easier to just run the commands in the terminal and edit the relevant files in Vim.
If you’re using Vim, add the following to your vimrc
1 2 |
" CocoaPods au BufNewFile,BufRead Podfile,*.podspec set filetype=ruby |
This will make the Podfile and podspec files get recognized as ruby files when doing syntax highlighting and indentation. If you’re using a different editor, you can check the CocoaPods GitHub page here to see if there are instructions for your text editor of choice.
It’s also really useful to set up a user defined function to allow the use of pod commands from within vim. If you recall, in vim’s command mode you can execute
1 |
:!<some terminal command here> |
And anything after the ! will be executed in bash with the output displayed. This makes it so you can execute :!pod install from within vim. Personally I dislike having to type out so much, so I added the following to my vimrc
1 2 |
:command -nargs=1 Pod !pod <q-args> :cab pod Pod |
The first line sets up a user defined function :Pod which executes :!pod with 1 argument. The second line sets up an abbreviation in command mode so that you can type “pod” and it will be replaced with “Pod”
Project Setup
The folder structure is very important.
1 2 3 4 5 6 7 |
. └── MyProject.xcodeproj ├── MyProject.xcworkspace <this will be generated by CocoaPods> ├── MyProject/ ├── Pods/ <this will be generated by CocoaPods> ├── Podfile └── Podfile.lock <this will be generated by CocoaPods> |
The Pods folder is the only one that should be in your .gitignore (or your respective source control system’s ignore file).
It is extremely important that the xcodeproj file is in the same folder as the xcworkspace. If it is not, then external resources will not be included in your project properly.
Podfile is a file CocoaPods uses to determine what pods you want to include. You can search for pods on the CocoaPods homepage. You can access the Podfile Syntax Reference here.
Once you have your Podfile setup, open the terminal and do the following
1 2 |
cd <folder containing your Podfile> pod install |
The first time you do this, it will take A LONG Time. The underlying architecture for looking up Podspec’s is a Git repository. This makes the pod install take a long time the first time you run it. This is normal.
Once the pod install runs, you can open up the xcworkspace and work to your hearts content.
If you’re using Git and you switch between branches, you will have to run pod install when you switch between branches, but don’t worry if you forget. When you try to build in Xcode, the build will fail and give you a nice error message if your Podfile.lock doesn’t match the installed pods.
When you run pod install, a specific version of each pod will be installed. If you want to update to a new version of a pod you will need to run pod update or pod update <name of pod> to update a particular pod. There’s more information on the Podfile.lock (serves the same purpose of Gemfile.lock) in this post.