CocoaPods is used in many iOS apps as a dependency management tool. You’ll see it being used in many open-source and enterprise applications. I had to learn this tool when I started working as an iOS developer.
How To Use CocoaPods?
It might seem like there are a lot of steps, but this saves you a ton of time compared to managing your own dependencies. I’ll explain each of the steps in greater detail throughout this article.
Integrating with can be a difficult process. You’re required to download frameworks and bundles to import into your Xcode project.
After that, you’ll have to link your binaries and add new linker flags. If this library depends on any other frameworks, you’ll have to do the whole thing over again!
This is can be a tedious, long process that adds a large amount of friction. If you need to update anything, you’ll have to search manually for updates on the internet.
When you find an update you’d like to install, you’ll have to update each library and its dependencies manually and re-link everything back together.
Making a mistake in this process could be disastrous for your iOS application. It could lead to crashes and unstable behavior. This detterred developers from using third-party libraries.
CocoaPods is a dependency manager specifically for adding 3rd party libraries. It simplifies this entire process! So you can use third party libraries with ease and not worry about all its dependecies.
to write a Pod Spec file. The Pod Spec file will contain information such as:
The Pod Spec file should list out anything the library needs to be installed. Luckily, CocoaPods will handle reading these files, so you don’t really need to worry about the details. As the developer, you just need to know the name of the Podspec file and optionally the version number (if you want a specific version).
Developers need to create a file called a Podfile. The Podfile lists the names and version numbers of the PodSpecs you’d like to use. CocoaPods will handle the rest.
Ruby Gems is a package manager for the Ruby programming language. That’s right, we’ll use a package manager to install another package manager.
If you don’t have Ruby Gems installed, you can do so by running the following commands on Mac:
brew update brew install ruby
You can also install Ruby Gems by checking out their download section their website here.
If you already have Ruby Gems installed, make sure it’s up to date. To update your gems tool, simply open up your terminal and run the command:
gem update --system
Once your gems has been updated, you’re ready to install CocoaPods.
Run this command in your terminal to install CocoaPods:
sudo gem install cocoapods
Alternatively, you can also install Cocoapods as a MacOS App. The download link can be found here.
Run pod setup in your terminal to download the master repo of CocoaPods. There are currently over 55 thousand libraries in the CocoaPods master repo.
This allows you to search through all the different pods available to download and install into your project.
The next step we’ll need to do is create Podfile for your project. There are two ways to do this, using pod init or to just use a blank file.
I recommend using a blank file as it’s simpler.
In your terminal, navigate to the same folder that your Xcode project is in, then create a new blank file named “Podfile” that contains your platform requirements and deployment target:
platform: ios, "11.0"
This tells CocoaPods that we’re building on iOS and 11.0 is our deployment target. The deployment target is the minimum iOS version that your app supports.
It’s important to list the deployment target as some libraries may only work on certain versions of iOS. When you tell CocoaPods the minimum version, it can point out problems to you ahead of time.
You can alternatively use the pod init function that will have some boilerplate.
Your project directory should look something like this.
Now you can list the pod specs of the libraries that you want to add. Unfortunately, there is no industry standard on how the pod specs are named. Luckily, you can just search for them in the command line using pod search.
So if you want to search for the Google Analytics, you could do:
pod search GoogleAnalytics
And you’ll receive a bunch of results like so:
The first result here is the one we want. You can see its homepage is pointing to google.com. The other libraries here are categories written by other developers that extend the capabilities of Google Analytics.
You can also search for libraries another way, by going to cocoapods.org and typing in the big search box.
Once we find the library we’d like, we can see how to install it by clicking the install guide button.
The squiggly line in ~> 3.17, means that pod should update this library automatically until 4.0. I go into detail about the version numbers in the Semantic Verisioning section of this article.
After we have all our libraries listed in our Podfile, we need to run pod install.
This is what my Podfile look like after adding AFNetworking and Google Analytics.
platform :ios, '9.0' target 'testing' do use_frameworks! pod 'AFNetworking', '~> 3.0' pod 'GoogleAnalytics', '~> 3.17' end
Now type pod install in your terminal:
Cocoapods will process for a bit, find the libraries from the internet and then install them into our workspace directory.
After running pod install, this is what my console output looks like:
Console output from pod install This saved you a ton of time! No need to download each library and each of its dependencies individually. The third party libraries are now installed and correctly linked to your project.
You’ll noticed after you ran pod install, CocoaPods gave you this warning:
Please close any current Xcode sessions and use testing.xcworkspace for this project from now on.
XCWorkspace files are a collection of projects. Cocoapods has created a workspace with our original project and our new Pods project. The iOS app project now depends on the statically built pods project.
If you open the project by itself, Xcode will complain that it cannot find the pod projects that your iOS app now relies on. You will get a bunch of linker errors if you open up your original project.
The same problem will occur if you try to open the project instead of the workspace from the Xcode welcome screen. So be sure to open up the .xcworkspace file instead of the .xcproject file.
Once your .xcworkspace is opened in Xcode, you’ll be able to run your iOS code with all your pods installed smoothly.
If you want to make sure you’re running the latest version of your libraries, you can simply just run pod updates from the command line.
CocoaPods will take care of everything else. All your pods and their dependencies will be updated and linked properly to your project. They will be updated according to your Podfile.
Remember you can specify if certain libraries update and to what version by changing the version of the library in Podfile.
You may have noticed that CocoaPods created a Podfile.lock in your project directory after you ran pod install.
If you open up your Podfile.lock you should see something similar to this:
PODS: - AFNetworking (3.2.1): - AFNetworking/NSURLSession (= 3.2.1) - AFNetworking/Reachability (= 3.2.1) - AFNetworking/Security (= 3.2.1) - AFNetworking/Serialization (= 3.2.1) - AFNetworking/UIKit (= 3.2.1) - AFNetworking/NSURLSession (3.2.1): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - AFNetworking/Reachability (3.2.1) - AFNetworking/Security (3.2.1) - AFNetworking/Serialization (3.2.1) - AFNetworking/UIKit (3.2.1): - AFNetworking/NSURLSession - GoogleAnalytics (3.17.0) DEPENDENCIES: - AFNetworking (~> 3.0) - GoogleAnalytics (~> 3.17) SPEC REPOS: https://github.com/cocoapods/specs.git: - AFNetworking - GoogleAnalytics SPEC CHECKSUMS: AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 GoogleAnalytics: f42cc53a87a51fe94334821868d9c8481ff47a7b PODFILE CHECKSUM: 481191f9d47c9d016112551b3f5a674ede21c501 COCOAPODS: 1.5.3
A CocoaPods lock file is important because it keeps track of every version of every library. It’s like a snapshot of exactly what CocoaPods has installed in your iOS project.
Lock files are very important if you’re working in a team environment. Let see an example to illustrate this point. Let’s say your Podfile looks like this:
platform :ios, '9.0' target 'testing' do use_frameworks! pod 'AFNetworking', '~> 3.0' pod 'GoogleAnalytics', '~> 3.17' end
I run pod install and it gets me version 3.0 of AFNetworking and 3.17 of Google Analytics.
Now, my teammate downloads the codebase and runs pod install. GoogleAnalytics has since updated to 3.20. So he gets AFNetworking 3.0 and GoogleAnalytics 3.20. This is a problem! We have different versions of Google Analytics party libraries.
Until I run pod update – I’ll be stuck on version 3.17. If my teammate starts using features that are not in the older version of GoogleAnalytics, it could potentially break my code when he merges in his changes!
A lock file prevents this from happening. By checking in your lock file into your code repository, everybody knows what version of the library you are using to build.
CocoaPods will read the lock file and install the correct version of GoogleAnalytics, even if there is a newer version of the library out there. This makes collaboration a lot easier, all your teammates will have the same version of third-party libraries installed.
If my teammate runs pod update, it will update to the new version of the library. But, this will also update the lock file, so the change will be recorded in the code repository.
The lock file acts a record of all the libraries and versions that your app has installed at any given time, assuming you use version control like Git. This enables you to go back in time and debug if a library update caused a bug.
This is up to you. Some people view the pod directory as derived data. This is because as long as you have a Podfile.lock and a Podfile, you should be able to recreate this directory easily.
However, if you don’t have CocoaPods installed – then you’ll need that pod directory. Some people argue that everything that’s required to run the project should be checked in. Your code repo will become slightly more bloated doing this method, as you’ll have to check in all the installed libraries.
This is less of a problem as hard drive space is typically minimal in cost. The bigger concern is if merge conflicts begin to occur in your pod directory. This can be a headache to fix, compared to just having merge conflicts in your Podfile or Podfile.lock.
Ultimately, the decision is up to you and your team. As long as everybody is on the same page, there should be no problem.
The squiggly arrow ~>, also known as a twiddle-wakka (I’m serious this is the official name) is important in determining the behavior of pod update.
In semantic versioning there are three numbers separated by periods. Something like “1.5.2.” The number on the farthest right is the patch number. The number in the middle is the minor release number. The number on the left, is the major release number.
The patch number increments every time the developer fixes a bug. Standard practice is that patch fixes should not break backward compatibility.
The minor number is increment when a new feature is added in a backwards compatible manner.
The major number is incremented when library authors make a change that breaks backwards compatibility.
So what does this have to do with the squiggly line? Let’s say you have version 1.5.2 installed, would you want CocoaPods to update to 1.5.3 when you call pod update?
This update is safe because the changes in 1.5.3 should be backward compatible. In most cases, you’d want to update.
Lets say you the library author releases 1.6.0. Do you want to upgrade from 1.5.3 to 1.6.0?
This update is also safe because its still backward compatible (Sometimes library authors break this rule…). In most cases, you’d also want to automatically update.
But wait, what about from 1.6.0 to 2.0.0? Do you want CocoaPods to automatically update in this case?
Probably not. When you run pod update, you don’t want to update to the next major version automatically as this could break some of your code. API signatures can change during major version upgrades.
The squiggly arrow means you’re ok CocoaPods updating your library, but only if it increments the last version number you specify.
For example ~> 1.5.1 can upgrade to 1.5.2, 1.5.3, 1.5.4 … etc. But CocoaPods will not update to 1.6.0
Another example is ~> 1.5, which can upgrade to 1.6.1, 1.7.5, 1.8.1 … etc. But CocoaPods will not update to 2.0.0.
CocoaPods also supports a number of standard operations such as
This all work as you would expect.
Remember Semantic Versioning is just a guideline, nobody is enforcing it and pods won’t be rejected because of it.
This is lesser known feature of CocoaPods. If you want to try out a library without installing it into your project, CocoaPods built a tool just for that!
For this example, we’re going to be trying out the library CorePlot. Open up your terminal and type this command in:
pod try CorePlot
You can type this command in any directory as long as you have CocoaPods installed. Your console output should look something like this:
XCode will then open up a workspace with a bunch of examples that you can try out.
Pod try is a great way to test out a library before installing it into your project! I only learned about this feature about 2 years into my iOS career! Wish I knew about it earlier, it makes evaluating third-party libraries a lot easier.
These two libraries are the best networking libraries for iOS development. They’re battle-tested and very popular amongst the iOS development community. They make basic networking to advance networking a lot easier.
You should use AFNetworking if you’re coding in Objective-C and Alamofire if you’re coding in Swift.
IGListKit is a data-driven
UICollectionView framework for building fast and flexible lists.
It’s built by Instagram engineering and is used in Instagrams home feed. Its main features include:
SwiftyJson is a great library that makes it super easy to deal with JSON in Swift. Since Swift is strictly typed (which is great, it prevents a lot of bugs), it makes it hard to deal with JSON, which is implicit about type.
This means when normally parsing JSON there are a lot of optionals and as? statements. SwiftyJson simplifies this syntax.
It’s a simple library, but makes the JSON parsing code look so much better!
Realm database is an alternative to SQLite and Core Data. It aims to simplify your database code by:
Realm is used by many startups, fortune 500 companies and has been downloaded over 2 million times. Here are some of the companies that use realm:
It also has support for multiple languages including:
If Alamofire is the peanut butter, Moya is the jelly. These two frameworks go very well together. Moya abstracts away classes like “APIManager” or “NetworkModel”. It makes the last mile of networking in your app beautiful.
This makes your app easier to develop, maintain and more testable. Some of this libaries features are:
Valet is a library written by the engineering team at Square.
Valet lets you securely store data in the iOS Keychain without knowing anything about Keychain. Square promises it to be an easy process. It has over 3000 stars on GitHub.
Google Analytics is probably the most popular analytics framework used today.
It lets you track data you care about such as installation, discovery, engagement, and conversion. It has over 25 million downloads!
Texture (formerly AsyncDisplayKit) keeps even the most complex iOS animations smooth. It’s was originally developed by Facebook and has recently been used for Pinterest’s app rewrite. Pinterest is now maintaining the library.
The library is also used by companies like Buffer, New York Times, and the NFL.
Texture works by moving the expensive UI operations off the main thread in order to prevent frame drops. The gold standard for iOS is 60 frames a second.
A simple drop-in library that displays an empty state when there is no content on a certain view. DZNEmptyDataSet helps you avoid blank white screens and quickly explains to the user what this view is for.
Chameleon is a color framework for iOS. It makes it easy for you to pick great colors and gradients.
Chameleons colors are flat and beautiful. It also supports making a color scheme from a primary color or an image.
Kingfisher is an awesome Swift library that handles downloading and caching different images from the web.
Some of its key features include:
Hero is a library that provides awesome smooth transition animations between UIViewControllers.
Here are some of the transitions it supports:
Charts helps you create pretty charts for your iOS app. It supports 8 different chart types including:
Making a CocoaPod is a simple process. The pod lib create tool creates a great library structure for you.
pod lib create [pod name]
Aside from the source code, the other files you’ll need to include are the
.podspec and the
LICENSE file. CocoaPods does not accept libraries without a license, as this could cause legal headaches down the line.
You can test your pod in your Xcode project by using a line like this in your Podfile:
pod 'Name', :path => '~/code/Pods/'
Test your own pod locally After that, you’ll want to test using the lint command of CocoaPods
cd ~/code/Pods/NAME pod lib lint
Before you release your pod to the general public, its important to test that you can download it from your repository and install it correctly. You can do this by using the following line in your Podspec file:
pod 'NAME', :git => 'https://example.com/URL/to/repo/NAME.git' pod install
If you want to learn more about creating your own Pod, check out these resources:
The Swift Package Manager is a dependency manager released by Apple. It comes included with Swift 3.0 and above.
It’s important to know that as of Swift 4.0, the Swift Package Manager has no support for iOS, watchOS, or tvOS platforms.
If you’d like to learn more about the Swift Package Manager, check out these two links:
Carthage is a decentralized dependency manager for iOS. It has similar goals to CocoaPods, aiming to be an easy way of adding frameworks to your application.
While CocoaPods automatically handles adding the binaries to your project, with Carthage, you’ll have to link these files manually. Carthage does this by design, the authors like the integration of the frameworks to be left up to the developer.
There’s also no central list of projects, this makes discovery of libraries more difficult. Users must rely on tools such as the trending section of Github.
Carthage aims to be more simple and acknowledges that it will never have some of the amazing features CocoaPods has.
To learn more about Carthage check it its GitHub repo here.
Do I need to use CocoaPods?
No, CocoaPods is used to integrate third party libraries easily. If you don’t want to use third party libraries or use a different dependency manager, CocoaPods is not required.
What’s the difference between Cocoa static libraries & frameworks?
Cocoa Touch Frameworks are always open-source and built like your app. This means Xcode will compile it sometimes when you run your app and always after a clean. Cocoa Touch Frameworks only support iOS 8 and above. They can be written in Swift & Objective C. Cocoa static libraries are already compiled when you import them into your project. They can be shared without being open source.
Should I use CocoaPods or Carthage?
For most developers, CocoaPods will be the better solution. You can use Carthage if you’d like more control on how the libraries are integrated into your application.