I’ve spoken about iOS dependency management before. It’s an important part of keeping any project clean and manageable (and built for the long term).

One thing I really like to do (especially when working on large teams - I’ve worked on codebases being hit by up to 30 iOS developers at once 😮) is create private CocoaPods for project modules. This allows us to share code across projects, and also helps with separation of concerns. The cool part? It’s really quite simple and can be done in about 5 minutes. I’ll walk you through the whole process with example projects. The steps will go like this:

  1. Make your module project (ie: your own model layer SDK)
  2. Create a repo for you module project on your local
  3. Tag the module project with a version number
  4. Create a private remote repo for your module project
  5. Push the module project repo up to your own private git remote
  6. Create a private podspec repo
  7. Create a podspec and push it to your repo
  8. Add the pod you just made to your podfile
  9. $ pod install baby!

So let’s get started!

1) Make your module project:

I’ve created an SDK for the Uber API called Aubergine. You can make something similar of your own, or just download the zip and use it for this example.

2) Create a repo for your module project on your local:

Make a directory for your module project, in this case we’ll use Aubergine, and initialize it as a git repository:

$ cd Aubergine && git init .

3) Tag the module with a version number

Commit to the master branch on your module project and give it a version number tag - in this case we’ll use 0.0.4 (more on versioning later)

$ git add . && git commit -m "0.0.4 drop"
$ git tag 0.0.4

4) Create a private remote repo for your module project

So here you need to specify some remote repo where you can push you module project to. Typically this would be a private internal repo (on something like a GitHub private repo, or Stash or GitHub Enterprise). You’ll give this remote a name which you can refer to in git - in this case, we’ll call it origin. So, from the terminal:

$ git remote add origin YOUR_REMOTE_URL_HERE

5) Push the module project repo up to your own private git remote

Then let’s push up our module project and tags to the remote:
$ git push origin master && git push origin 0.0.4


6) Create a private podspec repo on your local

Podspec files create all the information you need to add a CocoaPod to an Xcode project. They’re like a recipe containing the location of the CocoaPod files and a bunch of other information. For this part I’m assuming you have CocoaPods installed on your local. Make sure to have the latest version (0.38.2 at the time of writing). As an interesting and brief side exercise, run the following from your command line:

$ cd /.cocoapods/repos/master/Specs

You’ll notice there are a bunch of directories of CocoaPods which you may or may not be familiar with. This is called the “master” repo, and can be viewed at the CocoaPods GitHub repo. Nothing too crazy complex here - sometimes it just helps to know what we’re dealing with. But I digress, let’s make a private podspec repo. Come up with a name for the repo, in this case I’ll call it “tjprivatespecs”. On your remote git server create a brand new repo and run the following from your local:

$ pod repo add tjprivatespecs YOUR_PODSPEC_REPO_REMOTE_URL_HERE

Now you can take a look in your local CocoaPods directory and see your new specs repo right next to the master repo.

$ ls -al ~/.cocoapods/repos
total 0
drwxr-xr-x 4 tomjowett staff 136 11 Sep 15:06 .
drwxr-xr-x 3 tomjowett staff 102 9 Jul 20:12 ..
drwxr-xr-x 7 tomjowett staff 238 9 Jul 20:12 master
drwxr-xr-x 3 tomjowett staff 102 11 Sep 15:06 tjprivatespecs

Pretty cool! We’re starting to get a feel for how all this works under the hood, which will help us work faster and more effectively. Nice!

7) Create a podspec and push it to your repo

This is where it gets interesting. We need to make a ‘recipe’ for our pod. If you take a look in the Aubergine directory you’ll see a file Aubergine.podspec which looks like this:

Pod::Spec.new do |s|
s.name = "Aubergine"
s.version = "0.0.4"
s.summary = "An iOS SDK for the Uber API"
s.homepage = "https://github.com/tomj/Aubergine"
s.license = 'MIT'
s.author = { "Tom Jowett" => "[email protected]" }
s.source = { :git => "https://github.com/tomj/Aubergine.git", :tag => s.version.to_s }
s.platform = :ios, '7.0'
s.requires_arc = true
s.source_files = 'Aubergine/Classes/**/*'
s.dependency 'AFNetworking', '~> 2.4'
s.dependency 'Mantle', '~> 1.5.4'

This is the ‘recipe’ of the CocoaPod which was previously described. Everything is pretty self explanatory. If you’re making your own module project you’ll need to create a similar .podspec file and populate it with the appropriate contents. There’s a syntax reference for Podspec files over at CocoaPods. If you are following on with the Aubergine example, you’ll remember before that we used 0.0.4 as the tag for the version which we pushed to your private module repo. This part is important. Tags need to match up between the ‘recipe’ Podspec file being used and the tag on the module repo. Often this recipe will be committed to the module project itself - take a look at the popular CocoaPod AFNetworking for example - but it isn’t mandatory. Now for the magic part. We’re going to push this spec up to our own private spec repo. This is going to be like our own version of the CocoaPods master repo. Run the following:

$ pod repo push tjprivatespecs Aubergine.podspec --verbose

CocoaPods will do some magic (and will describe to us what it’s doing as we used the --verbose flag) and then will push up the Podspec to our private podspec repo. Note that this part is quite strict. There are a number of requirements when a pod is “linted” in this manner and if any of them are not met then pushing the Podspec will fail. It even takes care of the correct folder structure (it’s quite magical really). If you run ` $ open ~/.cocoapods/repos/` and expand the folders it should now look like this:

8) Add the pod you just made to your podfile

This one is pretty familiar to you all - make a new project (or modify the Podfile of an existing one) and add the following lines:

pod 'Aubergine'

9) Run pod install baby!

If you’ve read my post on Gemfiles you can run the following:
$ bundle exec pod install , otherwise a simple $ pod install will do here.

Look at that - you made your own private podspec repo. Boom!

Any issues, I’m happy to help - just leave comments down below ⬇️⬇️⬇️⬇️