Xcode and CocoaPods: A clean and errorless switch between branches with different pods

Arik Segal
CodeX
Published in
8 min readJan 7, 2023

A free simple shell script

When working with CocoaPods and xCode, a situation in which one branch of code has one set of pods and another branch has a different set, is quite common.

When the pods are different, switching from one branch to another (by using the Git Checkout command or by double-clicking the branch in a software like SourceTree) would normally cause errors the next time a Build operation is initiated from xCode. I will discuss the reasons for these errors in the “deeper dive into the problem” section. In most cases, running a Pod Install command after switching to the other branch would resolve the build errors, but sometimes this isn’t enough.

In this article I will introduce a simple script that does the following:

  • Exit xCode
  • Remove xCode’s derived data
  • De-integrate and re-install all pods
  • Re-open xCode

Running this script after checking out the other branch would insure that the pods are integrated correctly, and that all build errors (if there are any) are ”real”, and not just caused by the environmental change.

A deeper dive into the problem

Suppose our organization wants to develop a new page in the app, that will use a third party library for displaying charts. Assuming that we use the standard Feature Branch flow, the developer that this task was assigned to (Let’s call him Bill) would open a new branch. Let’s call the branch ChartsPageBranch.

Now let’s say that this same Bill is assigned another task: he is asked to develop a new page that will use different third party library, for displaying and managing a TicTacToe game. A different branch would be created for this.

So now Bill’s repository has the following structure:

Main

→ ChartsBranch

→ TicTacToeBranch

Luckily for Bill, thanks to CocoaPods, adding the libraries is rather straightforward. Let’s start with ChartsBranch. After creating the new branch, this is what needs to be done in order to start using the external library:

  1. Edit the Podfile and add the line Pod ChartsLibrary
  2. Run the command Pod Install from Terminal
  3. Run the app in order to verify that no harm was done
  4. Commit the Podfile modification and push the modified file to the remote repository. This will also involve choosing a name for the commit. A suitable name might be: “Added Pod ChartsLibrary to the Podfile”.
  5. Now the library can be referenced from code

Performing the above steps will download and integrate the new library including all dependencies. The same steps will be later repeated by Bill for integrating the TicTacToe library in to the TicTacToe branch.

The important thing to notice is this:

As far as the repository is concerned, the only change is that a single new line was inserted into the Podfile. But in reality, this is not the only thing that changed. What about the library itself? When running Pod Install, The downloaded library files were added under the Pods folder, but the contents of this folder are not tracked by Git and aren’t in the repository, so you won’t see this change when browsing through the commits history. As I wrote, all you will see is a new line in the Podfile and nothing more.

Why is that?

Since the contents of the Pods folder are automatically added by CocoaPods when Pod Install is executed, and since they are actually based on the content of the Podfile, the standard practice is to exclude the contents of the Pods folder from the repository, and only commit the modifications that were made to the Podfile. This is done by adding the line “Pods/” to the .gitignore file.

To ignore or not to ignore?

The author is trying to implement an Ignore gesture

Most of the standard ready-made .gitignore files that are suggested online, both for Swift and Objective C projects, contain a section like this one:


# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#

Even though the author of the file in this case recommends against it, in all places I ever worked in, the Pods folder is ignored.

Here is the should-i-check-the-pods-directory-into-source-control link for anyone who would like to read more about the pros and cons in this discussion:

And here is a summary of the pro’s, as stated in the article:

Benefits of ignoring the Pods directory

1. The source control repo will be smaller and take up less space.

2. As long as the sources (e.g. GitHub) for all Pods are available, CocoaPods is generally able to recreate the same installation.

3. There won’t be any conflicts to deal with when performing source control operations, such as merging branches with different Pod versions.

The major con is that when the project is cloned into a new computer, as a mandatory step, the developers will have to run Pod Install in order to integrate the third party libraries, and only then would they be able to build and run the app.

Now let us get back to our example.

Switching between branches with different pods

Bill has made nice progress in the Charts page, but, the organization has concluded that the TicTacToe page is more critical for its business logic, and the Charts page which is a “Nice to Have”, will be moved to the next sprint. This means that the Charts page will not be included in the approaching version, so Bill can now commit and push the charts’ work in progress and create the TicTacToe branch, which is now in higher priority.

The same steps that were previously discussed will now be applied to the TicTacToe branch:

1. Edit the Podfile and add the line Pod TicTacToeLibrary

2. Run the command Pod Install from Terminal

3. Run the app in order to verify that no harm was done

4. Commit the Podfile modification and push the modified file to the remote repository.

Now the library can be referenced from code

After this is done, the Podfile would be different for each of the two branches:

Main (common pods)

→ ChartsBranch (common pods + ChartsLibrary pod)

→ TicTacToeBranch (common pods + TicTacToeLibrary pod)

A few days has passed. The TicTacToe page is almost ready. However, The Android guy, let’s call him Igor, is preparing to start working on the Android version of the Charts page and needs to consult Bill about some implementation details in the code. So now, in order to view the Charts related code, Bill will need to switch back to the ChartsBranch.

For that, Bill can double-click the branch in a software like SourceTree, or use the Git Checkout command.

This is where we enter the twilight zone. Switching the branch did not install the Charts library, and when Bill tries to run the app he gets a “Module not found” error since the library is referenced from code and is not installed.

“You didn’t run Pod Install” says Igor (even though he is the Android guy he knows some other stuff as well).

“Of course, I keep forgetting that, when switching between branches with different pods”, says Bill.

A more complex case

Bill is lucky since all he has to do is Pod Install. In the HMO I work for, we had the following scenario:

  1. Our app has several methods of authenticating a registered user: Authentication can be performed by typing a password, or by requesting the server to send an SMS with a One Time Code (OTP). The networking tool that is used by our app in most cases is Moya, which is a very popular library.
  2. A third party app needed to use our user-authentication flow. For that purpose, we decided to migrate all of the relevant authentication methods, from our existing project into a new framework, to be used by the developers of the second app.
  3. Since the other app uses the latest version of Moya, and our code uses an older version, we had to align with them and migrate all of the methods in the new framework to use the Latest Moya.
  4. Since we don’t want to have the same functionality in two different places, we decided that it is only logical that our app should also use the framework for its authentication flow, in the same manner as the other third party app does. So we created a new version of our app that uses the framework for anything that has to do with authentication. This meant that we had to migrate all of the networking in our app to use the latest Moya.
  5. When developing the new version, occasionally I had to switch to the previous version.

In the above scenario we have the Main branch, in which the code expects to have Moya 13.0.0 installed, and the New Version branch, in which the code expects to have Moya 15.0.0 installed.

When trying to switch between the two branches we discovered that a Pod Install wasn’t enough, and the only way to avoid build errors was to implement the steps I mentioned at the beginning of this post:

  • Check out the other branch
  • Exit xCode
  • Remove xCode’s derived data
  • De-integrate and re-install all pods
  • Re-open xCode

Since it was boring and time consuming to have to perform all of the above steps whenever a switch is needed, we wrote the following script:

#!/bin/sh
echo "---- Closing Xcode ----"
killall Xcode

echo "---- Removing derived data ----"
rm -r ~/Library/Developer/Xcode/DerivedData

echo "---- De-integrating pods ----"
pod deintegrate

echo "---- Installing pods ----"
pod install

echo "---- opening Xcode ----"
open /Applications/Xcode.app

When I develop I always have a terminal window open so I can use this script whenever I need to, by typing:

./resetAll.sh

--

--