Back to Blog
iOS

From Objective-C to Swift: Practical Migration Lessons

March 15, 20248 min read

Why We Decided to Migrate

In 2017, I was leading the iOS team at Savvycom working on a live streaming platform for an international client. The app had been built entirely in Objective-C, and we were facing growing problems: new hires struggled with the codebase, bugs were harder to track down, and the lack of type safety was causing runtime crashes in production.

Swift had already matured to version 4 by then. We made the call to migrate — not a full rewrite, but a gradual, module by module approach.

The Strategy: Incremental, Not Big Bang

The biggest mistake teams make is trying to rewrite everything at once. We chose a different path:

  • New features in Swift only — Any new screen, service, or utility was written in Swift from day one.
  • Bridge layer first — We created clean bridging headers and ensured Objective-C and Swift could coexist without friction.
  • Migrate by module — We prioritized modules with the most bugs or the most active development. The networking layer went first, then the data models, then the UI components.
  • Keep shipping — We never stopped releasing. Every sprint had both feature work and migration work.

Challenges We Didn't Expect

The Bridging Header Nightmare

Objective-C categories, macros, and C functions don't always translate cleanly to Swift. We spent entire days debugging issues where a bridged enum had different raw values or a category method was invisible to Swift.

Lesson learned: Audit your Objective-C code for Swift compatibility before you start. Look for variadic functions, complex macros, and C constructs that won't bridge.

Singleton Patterns

Our Objective-C code was full of singletons using dispatch_once. In Swift, singletons are trivial (static let shared), but the migration meant two versions of the same singleton could exist simultaneously — one in Objective-C, one in Swift.

We solved this by keeping the Objective-C singleton as the source of truth and wrapping it with a Swift interface until the dependent code was fully migrated.

Core Animation and WebRTC

The app relied heavily on Core Animation for gift effects and WebRTC for live streaming. These layers were deeply integrated with Objective-C runtime features like method swizzling and KVO. We decided to keep these modules in Objective-C and wrap them with Swift protocols.

Lesson learned: Not everything needs to be migrated. If a module is stable, well tested, and rarely changed, wrapping it is better than rewriting it.

What We Got Right

Protocol Oriented Design

Instead of directly converting Objective-C classes to Swift classes, we introduced protocols first. This let us define clean interfaces, write unit tests against protocols, and swap implementations without breaking existing code.

Automated Testing as a Safety Net

Before touching any module, we wrote integration tests for its public API. This gave us confidence that the migrated Swift version behaved identically to the Objective-C original.

Pair Programming During Migration

We paired senior developers (who understood the Objective-C codebase) with junior developers (who were stronger in Swift). This knowledge transfer was invaluable and prevented both tribal knowledge loss and migration mistakes.

Results

After 4 months of incremental migration:

  • 60% of the codebase — was in Swift
  • Crash rate dropped by 35% — thanks to Swift's type safety
  • Onboarding time for new developers — went from 3 weeks to 1 week
  • Feature development velocity — increased noticeably

Key Takeaways

  • Never do a big bang rewrite. — Migrate incrementally, keep shipping.
  • Bridge, don't break. — Make Objective-C and Swift coexist cleanly before migrating.
  • Wrap stable modules. — Not everything needs to be rewritten — sometimes a Swift wrapper is enough.
  • Test before you touch. — Write integration tests for any module before migrating it.
  • Pair your team. — Migration is a knowledge transfer opportunity, not just a technical task.

If you're facing a similar migration, feel free to reach out. I'm happy to share more details about the specific patterns and tools we used.