How to Convert a full ObjectiveC app to Swift

At GoogleCast, we migrated a reference iOS app to Swift using an app, compiler, simple rules and a linter. Here’s what we learned.

Ibrahim Ulukaya
Apr 3, 2017 · 4 min read

Recently @ToddKerpelman and I converted a reference iOS Google Cast app to Swift. Before, I implemented Firebase iOS quickstarts. I created both ObjectiveC and Swift target at the same time. But I never tried to migrate a full app to Swift before. So I welcomed this challenge.

Blame me being lazy. I didn’t want to do to mundane work of declaring each variable and function in Swift. I decided to take a leap in faith and try a converter tool as a starter. I was going to see how good it can translate. Then I was going to catch build errors and bugs after checking line by line. Finally I was going through with a linter tool to catch any bad style.

After googling “ObjectiveC to Swift converter” I decided to give a try to Swiftify. I did a test on a small file, it looked good. Then I uploaded the whole project, pressed convert button, closed my eyes and hoped for the best.

What I received looked like a Swift code. There were double definitions of the variables as they got imported from both .h and .m. Some of the definitions that should’ve been on the top of the file were on the bottom. But in general it looked like I saved tons of hours of mundane work to fix dots and parentheses. Because of the original code, I even saw definitions like private(set) public var. We started with 269 build errors (more like 800 as you fix, you get more :). Luckily there were lots of low hanging fruits:

  • double definitions of vars
  • wrong optionality, function signatures
  • Swift 3 style issues (enumeration naming)
  • Xcode suggested fixes (nullability checks).

This took 3 days as we go down all the way to 2 digits. Now the no-brainer bugs were gone. We had to use assistant view to fix remaining bugs side by side. Most of the bugs turned out to be wrong guesses on the optionality types of class vars. Converter always picks implicitly unwrapped variables instead of optionals. Or it would try to guess local variable types wrong. (You don’t need to declare variable types most of the times as Swift can infer them). Only because I was eager to see the app built, I took a shortcut. I used force unwrapping and force casting only to get rid of build errors. Little did I know, I was going to pay a high price for this later on debugging. After bunch of var to let conversions (converter defined all variables as var), we had an app that built!

Don’t get so hyped yet, we were only beginning. Yes, our app was building, but returning no data and crashing at startup. We spent the next 100 hours debugging to find all the

  • null errors
  • wrong if not null checks,
  • and lots of optionality fixes.

After those, our app was initializing. It was “almost” casting, yet another force unwrapping error.

There is a reason for style guides. They help you to use the language the way it was designed to be used, and they prevent most bugs before you create them. At that moment SwiftLint came to rescue. You can run SwiftLint on Xcode to see all the style guide exceptions on the lines they occur, and fix them quick. I was determined to get rid of all optionality bugs and stay close to style guide as much as possible. I enabled even the opt-in rules. Fixing style not only helped the readability, but also improved our confidence on the errors. We found further bugs on the way. We got rid of all the force unwrapping, force casting, explicit type declarations, implicitly unwrapped optionals. We favored if let and guard let statements wherever possible.


We will be refactoring the app in next weeks, but at least, we have a 1-to-1 swift port of the CastVideos sample app now.

  1. Swiftify saved us valuable time instead of converting the project line by line. (As long as you now it’s not going to do the all work for you. It’ll be a guesstimate)
  2. Never ever use ! (unwrapping symbol) unless you have no other choice. Force unwrapping myVar!, force casting as!, implicitly unwrapped optionals Type! are very prone to errors.
  3. Replacing them with if let, guard let, and optional chaining x?.y?.do() will recover your app from exceptions instead of crashing and will help you in debugging.
  4. Style guides both improves readability and make your code less prone to bugs. SwiftLint was a great tool to force the Swift style guide.

Google Developers

Engineering and technology articles for developers, written…

Google Developers

Engineering and technology articles for developers, written and curated by Googlers. The views expressed are those of the authors and don't necessarily reflect those of Google.

Ibrahim Ulukaya

Written by

iOS Engineer. Adventurer. @Firebase

Google Developers

Engineering and technology articles for developers, written and curated by Googlers. The views expressed are those of the authors and don't necessarily reflect those of Google.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store