Most of us use open source libraries on a daily basis. With CocoaPods, managing dependencies in a Cocoa project is virtually painless. In some situations, however, a project depends on a library or framework that is closed source, not publicly available. You can still use CocoaPods in such situations. CocoaPods works great for both closed and open source libraries.
To make this work, you need to create a private specs repository. Once you've set one up, you don't even notice the difference between public and private dependencies, because CocoaPods takes care of the nitty gritty details for you. In this tutorial, you'll learn how to set up a private specs repository to manage private libraries.
1. Introduction
If you've only used CocoaPods for managing public pods, then you may not know that CocoaPods can handle multiple specs repositories. If no specs repository is specified in the project's Podfile, CocoaPods falls back to the master specs repository.
If you specify a dependency in your project's Podfile, CocoaPods searches by default in the master specs repository. Take a look at the following two examples. Both examples generate the same result. The difference is that we explicitly specify the source of the specs repository in the second Podfile.
platform :ios, '8.0' target 'Testing' do pod 'AFNetworking', '2.6.0 ' pod 'SVProgressHUD', '~> 1.1' end
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'Testing' do pod 'AFNetworking', '2.6.0 ' pod 'SVProgressHUD', '~> 1.1' end
If you've never created or contributed to a pod, then you may be wondering what a specs repository is? A specs repository is nothing more than a repository that contains a collection of pod specifications, files with a .podspec or .podspec.json extension.
As the name suggests, the specs repository doesn't contain the source files for the pods. You can browse the CocoaPods master specs repository on GitHub. If CocoaPods is installed on your machine, however, then a copy of the master specs repository is already present on your machine.
During the installation process, CocoaPods clones the master specs repository to your home folder. You can find it at ~/.cocoapods/repos/master.
2. Creating a Specs Repository
I usually use GitHub for hosting Git repositories so that's the platform I'll be using for this tutorial. It doesn't matter where you host the specs repository as long as it's accessible by everyone on your team.
You can create a free GitHub account to follow along, but keep in mind that you can only create public repositories with a free account. If you have a library that you want to open source, then it's recommended to publish the pod spec to the master specs repository, which is managed by the CocoaPods team. You don't gain anything by creating a separate public specs repository.
The first thing we need to do is create a private repository on GitHub for the private specs that we're going to add later. I've named mine tutspods. GitHub will suggest to clone the repository to your machine, but that isn't necessary. CocoaPods will clone the specs repository for you once you've added it to CocoaPods. That's what we'll do in the next step.
3. Adding the Repository to CocoaPods
The next step is telling CocoaPods about the specs repository we just created. You do this by executing the following command from the command line.
pod repo add tutspods https://github.com/bartjacobs/tutspods.git
You may notice that the command is similar to adding a remote to a Git repository. Make sure that you remember the name you give the specs repository, tutspods in this case. We'll be needing it a bit later.
Whenever you add a specs repository, CocoaPods clones the repository to your machine. You can verify this by navigating to ~/.cocoapods/repos. The directory should now contain two specs repositories, the master specs repository and the tutspods specs repository. Apart from a .git folder, the tutspods directory is empty since we haven't added any specs yet.
4. Creating a Private Pod
Not too long ago, Andy Obusek wrote a great tutorial about creating your first pod. If you've never created a pod—public or private—then I recommend reading Andy's article first. I won't repeat what Andy wrote in this tutorial.
As an example, I've created a tiny library, TSPTableView, which contains a special UITableView
subclass. To create a pod spec for the library, run the following command in the root of the library.
pod create spec TSPTableView
By running the above command, CocoaPods creates a file named TSPTableView.podspec. Open the file in a text editor and fill out the required fields. When you're done, run pod spec lint
to validate the pod spec. If the pod spec doesn't pass validation, you won't be able to push the spec to the specs repository.
5. Pushing the Spec to the Specs Repository
If the pod spec passes validation, it's time to push it to the private specs repository you created earlier. You do this by executing the following command from the command line.
pod repo push tutspods TSPTableView.podspec
It's key that you use the same name you previously used to add the private specs repository to CocoaPods. The last argument is the path to the pod spec you're pushing to the specs repository.
6. Using the Private Pod
We can now use TSPTableView in a new project. Create a project in Xcode and add a Podfile at the root of the project by running pod init
from the command line. This is what the Podfile could look like when you're finished.
platform :ios, '8.0' target 'MyAmazingApp' do pod 'TSPView' end
Run pod install
from the command line to install the dependencies listed in the project's Podfile. Did you also run into a problem? I see the following error.
pod install Updating local specs repositories Analyzing dependencies [!] Unable to find a specification for `TSPTableView`
The output tells us that CocoaPods first updates the local specs repositories. This means that the repositories in the ~/.cocoapods/repos directory are updated, pulling in any changes.
CocoaPods does this to ensure that it has the latest version of the specs that are stored in the repositories. If we take a look at the ~/.cocoapods/repos/tutspods directory, we can see that the pod spec for the TSPTableView pod is there like we expected. Why can't CocoaPods find the pod spec for TSPTableView?
The solution is simple. At the top of the Podfile, we need to specify which specs repositories CocoaPods searches to resolve the dependencies listed in the project's Podfile. This is what the Podfile should look like to remedy our issue.
source 'https://github.com/bartjacobs/tutspods.git' source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' target 'MyAmazingApp' do pod 'TSPTableView' end
Run pod install
one more time to install the dependencies listed in the project's Podfile. The command should now finish successfully as shown below. I'm currently using CocoaPods 0.38.2 so the output may be slightly different if you're using a different version of CocoaPods.
pod install Updating local specs repositories Analyzing dependencies Downloading dependencies Installing TSPTableView (0.0.1) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `MyAmazingApp.xcworkspace` for this project from now on.
Note that the order in which you list the specs repositories in the Podfile is important. For example, if you've forked a public pod, modified it, and created a private pod for the fork with the same name, you will have a naming collision.
This isn't a problem for CocoaPods, because it will use the first pod it can find with the specified name. In general, you should put the private specs repository at the top to make sure CocoaPods searches that one first, falling back to the public specs repository if necessary.
Conclusion
CocoaPods is a great tool that I wouldn't be able to work without. I hope this tutorial has shown you how powerful CocoaPods is and how easy it is to create and manage private pods with CocoaPods.