Using Cocoapods in Large Scale Apps

SHARE

We love using CocoaPods to manage dependencies in all our iOS projects, it enables us to create a project and start working in literally few minutes!

However I started having some hard times keeping my iOS projects in sync with what the amazing Swift community is doing, not only the language is changing fast, but projects as well, new projects are born and old ones are being refactored and replaced quickly.

In this tutorial, I’ll explain a suggested workflow for managing 3rd party dependencies and how to make the Podfile, well, a little bit more interesting 😉

Let’s assume that we’re working on version 1.0.0 of a project that has the codename Apollo

A codename is a something we use at my company to identify our project publicly while in development without disclosing much information about them.

Semantic Versioning is what we use for versioning.

Let's also assume that the following dependencies have to be used to build the project

For each project from the dependencies above:

  1. Fork the dependency to our GitHub organization account
    • If the project is already forked, make sure to sync the fork with upstream to get the latest updates before proceeding, more here.
  2. Create a new branch — from wherever the current stable release is — with the name {codename}-{version}, for our example it will be apollo-1.0.0
  3. Use the following template to add dependencies to our Podfile:
platform :ios, '9.0'

# Global variables
REPO = 'https://github.com/GITHUB_ORGANIZATION_NAME'
BRANCH = 'CODENAME-VERSION'

target 'TARGET_NAME' do
    use_frameworks!

    ## Dependencies
    pod 'LIBRARY_1', git: "#{REPO}/LIBRARY_1", branch: "#{BRANCH}"
    pod 'LIBRARY_2', git: "#{REPO}/LIBRARY_2", branch: "#{BRANCH}"
  # ...

end

For our example:

platform :ios, '9.0'

REPO = 'https://github.com/GITHUB_ORGANIZATION_NAME'
BRANCH = 'apollo-1.0.0'

target 'Apollo' do
    use_frameworks!
    pod 'RxSwift', git: "#{REPO}/RxSwift", branch: "#{BRANCH}"
    pod 'Moya', git: "#{REPO}/Moya", branch: "#{BRANCH}"
    pod 'Kingfisher', git: "#{REPO}/Kingfisher", branch: "#{BRANCH}"

end

Benefits

  • Have all 3rd party dependencies versions used in a specific version of our app is now grouped by a single keyword, say it is 1 year later, the current version for project Apollo is 4.3.0 and we want to debug something in version 1.7.0, all we have to do is just update the version number in Podfile, and perform a quick pod update.
  • We own a copy of any open-source dependency we use, if the maintainer decided to shutdown the project, well, at least we have more time to evaluate other options, or if it is important enough, maybe continue developing our fork.
  • Cherry-picking code from a dependency becomes as easy as creating a branch and update the code to keep only what we need, and remove what we don’t.
  • Fix bugs faster than dependencies maintainers sometimes.
  • Hopefully this will help other developers in our team to contribute back as soon as they fix any bug, We’re not sure, let’s see how this will go for a while :)

We’re now working on a script to update our forks, create new branches, update the Podfile and automate the whole process.

If you have any questions or suggestions, don’t hesitate to reach out to me on Twitter.

CocoaPodsMacOSRubySoftwareSwiftiOStvOSwatchOS

You made it to the end. You're Awesome!

Here is something more to read

Protocol Oriented Extensions

Use the power of protocols and generic types to avoid extension conflicts

Making MVC Great Again!

Use generics, protocols, and extensions to get rid of massive view controllers

This is a fully integrated open-source project that uses NextJS, Redux, and Django to build. Grab your copy from Github

Copyright © 2019 Omar Albeik. All rights reserved.