How We Migrated Our Ad SDKs from CocoaPods to Swift Package Manager at Grindr

Grindr
&
Editorial team
October 15, 2025
6
min. read
Table of Contents
TABLA DE CONTENIDOS
ÍNDICE DE CONTEÚDO

At Grindr, we’re always looking for ways to simplify our development process. One goal that kept coming up was: “Let’s use only one dependency manager across all our codebase.” And that meant saying goodbye to CocoaPods and fully embracing Swift Package Manager (SPM).

For the most part, it was a smooth transition until we got to our Ads stack, which includes AppLovin and a variety of mediation adapters. That’s where things got tricky.

This is the story of how we worked around those limitations, reused what CocoaPods gave us, and built a tool to generate a working Swift package from a bunch of .xcframeworks.

Why did we need to build our own Swift package?

If you’ve ever worked with AppLovin, you know the core SDK supports SPM. But what about the mediation adapters (Unity, GAM, HyBid…)? Not so much.

“Note, this Swift package only includes the main AppLovin MAX SDK. We currently do not support installing MAX mediation network adapters using Swift Package Manager.”
https://github.com/AppLovin/AppLovin-MAX-Swift-Package

At the time, most of AppLovin’s adapters were still only available via CocoaPods. That meant if we wanted to use SPM for everything (hint: which we did), we’d need a custom workaround.

After a bit of digging, we noticed something interesting: when you run pod install, CocoaPods downloads precompiled .xcframeworks for many of these dependencies.

That gave us an idea: What if we could take those .xcframeworks and use them to build our own Swift package?

This is how our idea came through...

Step One: Build a Fake Project

To test our idea, we created a minimal project with a Podfile that included AppLovin and all the mediation adapters we use. We ran pod install, and just like we hoped, many of the SDKs were downloaded as .xcframework bundles.

So far, so good.

But not everything was perfect. Some dependencies didn’t come with .xcframeworks at all; they were just pulled in as source code.

Step Two: Hunt for Binaries

For those source-based dependencies, we had to get creative, e.g HyBid.

We visited GitHub releases, vendor documentation, or artifact servers to manually find the correct .xcframework versions. It wasn’t elegant, but it worked, and once we had all the binaries in one place, we could move forward.

Step Three: Automate All the Things

We knew we didn’t want to repeat this process manually every time. So we built a set of scripts to automate everything:

  • Generate the temporary CocoaPods project (XcodeGen)
  • Run pod install
  • Collect all the .xcframeworks
  • Organize them into a clean directory (automated with a script)
  • Generate a Package.swift file using binaryTargets
  • Automatically compute the checksums for remote .zip packages (like AppLovin and HyBid)

In the end, we had a reproducible pipeline that turns a set of binary frameworks into a proper Swift package.




Validating Everything Works

Once we had the package integrated into the main app, we did a full test sweep:

Everything rendered correctly and loaded as expected, but as with any dependency migration, we hit a few bumps along the way.

Duplicate Symbols and Module Conflicts

Initially, we noticed that some builds failed due to duplicate symbol errors. This happened because a few .xcframeworks shared internal symbols across modules, or some were being linked more than once due to improper dependency declarations.

To resolve this, we had to carefully restructure the binary targets, ensuring that:

  • Dependencies were declared only once per product.
  • Wrapper targets were created for certain SDKs (e.g., AppLovin) to control linker behavior.
  • Shared modules weren’t pulled in multiple times through transitive dependencies.

Controlling Linkage Behavior in SPM

Unlike CocoaPods, SPM handles linking automatically, which usually works well, but for performance-sensitive frameworks like ad SDKs, we needed more control.

We introduced custom .target entries with explicit linkerSettings, making sure the required system frameworks were statically linked. This helped us:

  • Avoid increased launch times.
  • Prevent SPM from defaulting to dynamic linking for certain modules.
  • Match the behavior of our previous CocoaPods integration.

Handling Google SDKs with High Coupling

Some Google libraries (like GoogleMobileAds) have complex transitive dependencies, and managing them manually through .xcframework references proved brittle.

What We Learned

  • CocoaPods remains a practical tool for resolving and extracting binary artifacts
    While SPM is our long-term solution, CocoaPods can still serve a transitional purpose, particularly when dealing with SDKs that don’t yet expose precompiled binaries via .xcframework.zip. It reliably resolves versioned dependencies and materializes the .xcframeworks we can later repackage for SPM.
  • Swift Package Manager supports complex setups via binaryTarget and custom linkage
    SPM’s binaryTarget support allows for clean integration of precompiled frameworks, even in ecosystems not originally designed for it. Combined with target configurations for linking system frameworks and setting linkerSettings, it provides the necessary tools to replace CocoaPods in binary-focused setups.
  • Automating the pipeline eliminates manual, error-prone work
    By scripting the generation of Package.swift, dependency resolution, and checksum calculation, we created a reproducible and scalable process. This ensures consistency across environments (CI/local), reduces onboarding friction, and avoids configuration drift.
  • Explicit project structure improves maintainability and clarity
    Separating concerns into dedicated directories — one for framework artifacts, one for script logic, and one for the generated package — brings transparency to the system. This makes it easier to maintain, debug, and evolve the tooling over time without unintended side effects.

https://developer.apple.com/documentation/xcode/distributing-binary-frameworks-as-swift-packages

https://www.emergetools.com/blog/posts/make-your-ios-app-smaller-with-dynamic-frameworks#building-our-xcframework

Share this article
Comparte este artículo
Compartilhe este artigo

Find & Meet Yours

Get 0 feet away from the queer world around you.
Thank you! Your phone number has been received!
Oops! Something went wrong while submitting the form.
We’ll text you a link to download the app for free.
Table of Contents
TABLA DE CONTENIDOS
ÍNDICE DE CONTEÚDO
Share this article
Comparte este artículo
Compartilhe este artigo
“A great way to meet up and make new friends.”
- Google Play Store review
Thank you! Your phone number has been received!
Oops! Something went wrong while submitting the form.
We’ll text you a link to download the app for free.
“A great way to meet up and make new friends.”
- Google Play Store review
Discover, navigate, and get zero feet away from the queer world around you.
Descubre, navega y acércate al mundo queer que te rodea.
Descubra, navegue e fique a zero metros de distância do mundo queer à sua volta.
Already have an account? Login
¿Ya tienes una cuenta? Inicia sesión
Já tem uma conta? Faça login

Browse bigger, chat faster.

Find friends, dates, hookups, and more

Featured articles

Artículos destacados

Artigos em Destaque

Related articles

Artículos relacionados

Artigos Relacionados

No items found.

Find & Meet Yours

Encuentra y conoce a los tuyos

Encontre o Seu Match Perfeito

4.6 · 259.4k Raiting
4.6 · 259.4k valoraciones
4.6 · 259.4k mil avaliações