Carthage Tutorial: Getting Started

In this Carthage tutorial, you’ll learn what Carthage is, how to install it and how to use it to declare, install and integrate your dependencies. By Felipe Laso-Marsetti.

Leave a rating/review
Download materials
Save for later
Share
Update note: Felipe Laso Marsetti updated this tutorial for iOS 13, Xcode 11 and Swift 5. James Frost wrote the original.

One of the great things about iOS development is the wide range of third-party libraries available to use. If you’ve tried some of these libraries, you know the value of using someone else’s code instead of reinventing the wheel.

With so many libraries available, managing dependencies can get tricky. That’s where dependency managers come in.

Carthage is a simple dependency manager for macOS and iOS, created by a group of developers from GitHub.

Not only was Carthage the first dependency manager to work with Swift, but it’s also written in Swift! It exclusively uses dynamic frameworks, rather than static libraries.

In this Carthage tutorial, you’ll:

  • Learn why and when to use a dependency manager and what makes Carthage different from other tools.
  • Install Carthage.
  • Declare dependencies, installing and integrating them within a project.
  • Upgrade your dependencies to different versions.

You’ll do this by building an app that provides definitions for search terms using the DuckDuckGo API.

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the starter project.

It includes the basic skeleton of DuckDuckDefine, a simple tool to look up definitions and images using the DuckDuckGo API. There’s one problem: It doesn’t perform any searches yet!

Open DuckDuckDefine.xcodeproj in Xcode and have a quick look. Note the two view controllers: SearchViewController provides a search bar for the user to perform a search and DefinitionViewController displays the definition of a search term.

Looking at the files in the Project Navigator

The brains of the operation are in DuckDuckGo.swift – well, they will be by the time you finish! At the moment, performSearch(for:completion:) is a lazy, good-for-nothing block of code.

To perform a search and display the results, you’ll need to do two things:

  • Make a query using the DuckDuckGo API.
  • Show an image for the retrieved word.

There are many open source libraries that can help with these two tasks. Alamofire is a great Swift library that simplifies making web requests. AlamofireImage makes dealing with images in Swift more pleasant.

And guess what? You’ll use Carthage to add both of these dependencies to your project.

Advantages of Dependency Management

To add Alamofire and AlamofireImage to your project, you could visit their respective GitHub pages, download zip files containing their source code and drop them into your project. So why bother with a tool like Carthage?

Dependency managers perform some handy functions, including:

  • Simplifying and standardizing the process of fetching third-party code and incorporating it into your project. Without this tool, you’d do this by manually copying source code files, dropping in pre-compiled binaries or using a mechanism like Git submodules.
  • Making it easier to update third-party libraries in the future. Imagine having to visit each dependency’s GitHub page, download the source, and place it into your project every time there’s an update. Why would you do that to yourself?
  • Selecting appropriate and compatible versions of each dependency you use. For instance, manually adding dependencies can get tricky when they depend on one another or share another dependency.

How dependency management works as a hierarchy

Most dependency managers construct a dependency graph of your project’s dependencies and their sub-dependencies, then determine the best version of each to use.

You could do the same manually, but at what cost? Your sanity? Dependency managers are easier and less error-prone.

Comparing Dependency Managers

One of the most popular dependency managers is CocoaPods, which streamlines integrating libraries into your project. It’s widely used in the iOS community.

Apple offers its own dependency manager called Swift Package Manager to share and distribute packages in Swift 3.0 and above.

While CocoaPods and Swift Package Manager are great tools, Carthage offers a simpler and more hands-on alternative. So which one is right for you? In the next section, you’ll compare Carthage with some of the other popular tools.

Carthage Versus CocoaPods

How is Carthage different from CocoaPods, and why would you use anything besides the most popular dependency manager for iOS?

While CocoaPods is easy to use, it is not simple. The philosophy behind Carthage is that a dependency manager should be simple.

CocoaPods adds complexity to the app development and the library distribution processes:

  • Libraries must create, update and host Podspec files. App developers must write their own if none exist for a library they wish to use.
  • When adding pods to a project, CocoaPods creates a new Xcode project with a target for each individual pod, plus a workspace to contain them. You have to use the workspace and trust that the CocoaPods project works. You also have to maintain those extra build settings.
  • CocoaPods uses a centralized Podspecs repository. This can disappear or become inaccessible, causing problems.

Carthage aims to provide a simpler tool that’s more flexible and easier to understand and maintain.

Here’s how Carthage achieves this:

  • It doesn’t change your Xcode project or force you to use a workspace.
  • You don’t need Podspecs or a centralized repository where library authors submit their pods. If you can build your project as a framework, you can use it with Carthage, which leverages existing information straight from Git and Xcode.
  • Carthage doesn’t do anything magically; you’re always in control. You add dependencies to your Xcode project and Carthage fetches and builds them.
Note: Carthage uses dynamic frameworks to achieve its simplicity. This means your project must support iOS 8 or later.

Carthage Versus Swift Package Manager

How about the differences between Carthage and Swift Package Manager?

The main focus of the Swift Package Manager is to share Swift code in a developer-friendly way. Carthage’s focus is to share dynamic frameworks. Dynamic frameworks are a superset of Swift packages.

A package is a collection of Swift source files plus a manifest file. The manifest file defines the package’s name and its content. A package contains Swift code, Objective-C code, non-code assets like images or any combinations of the three.

SPM has a lot going for it, especially since Xcode 11 has built-in support for SPM packages. However, at the time of writing, SPM has a couple of limitations that prevent a lot of libraries from supporting it. For instance, it doesn’t support sharing already built binaries, only the source code of your packages. If you want to have a closed-source library, you can’t use SPM. Additionally, SPM supports adding source code to frameworks, but not resources like images or other data files.

This means that a lot of libraries you might use won’t get SPM support anytime soon. For now, you’ll still have to rely on Carthage or CocoaPods for those libraries.