Discover everything about my personal works as a game dev, mostly on Apple platforms

Objective-C to Swift - The Journey - Part 1

Nihongo no Kana

Nihongo no Kana was initially released in May 2012. It was the days of the iPhone 4S, of the very first iPad Retina and of iOS 5. The ecosystem was still in its infancy but was obviously already tremendously popular. So, many developers became familiar with Objective-C, a strange language in many regards, yet instrumental to create those precious 3rd-party native apps.

Fast forward to 2021. In about ten years, the programming landscape has changed a lot. The popularity of JavaScript and C# exploded. Java came back front and center thanks to Android. And C, C++ and Objective-C lost ground. Apple had to react, introducing Swift in 2014 and focusing most of its efforts on this new language since then. SwiftUI came after that in 2019.

As a side project, done during my ever decreasing free time, I never managed to produce more than one or two updates a year of Nihongo no Kana. It is truly an educational project on every aspect. Educational by essence as the app is designed to help you memorize the basics syllabaries of the japanese language. And educational for myself as I’ve originally made it to learn how to code in Objective-C. And educational it will remain as I use the project to learn SwiftUI.

Why Moving To Swift?

First and foremost, to learn the language. So far, I have made some experiments and a small Tetris recreation, but it will be my first full app combining Swift and SwiftUI.

The other reason is also very simple. Even if as the time of writing, Objective-C remains a fundamental player in the Apple developmer ecosystem (for example, Swift cannot talk directly to C/C++ and relies on bridges written in Objective-C or Objective-C++). it will inevitably continue to lose ground and many of the missing features will be progressively added to Swift over time.

SwiftUI is also a big deal and a very welcome evolution. Previously, you had two options: doing everything programmatically (without preview), or using Interface Builder to create your interface visually and link it to your code. But the files generated by Interface Builder (xib, nib or storyboards) are heavy and cryptic XML assets that are a nightmare to work with in a team. Merge conflicts are utterly difficult to resolve. On the other hand, SwiftUI provides a declarative language, all done in code, but with elegant (even if not very stable yet) previews.

SwiftUI Previews in Xcode SwiftUI Previews in Xcode

The Challenges

Migrating an Objective-C / Interface Builder app needs some planing.

First, Nihongo no Kana is almost 10 years old. Even if it has seen a refresh when version 2.0 was introduced, the overall structure remained mostly the same. It feels old now. So, recreating the exact same interface in SwiftUI is probably not the best approach.

Second, a lot of the underlying code is not directly tied to the interface and will be useful even with a complete redesign. Also, this is where most of the bugs would likely lie after the migration. It is also completely possible to maintain compatibility with the existing Interface Builder assets while running the code in Swift. There are also some deprecation issues related to CoreData that need to be addressed.

The Path Forward

A visual redesign of the app will take a long time and must probably be done in a single massive step. On the other hand, discretly evolving the code may be done in the background, providing several intermediary updates to the App Store.

The app currently sits at version 3.0.3 and requires iOS 9. The fully-transitioned app will be ultimately released as version 4.0. In the meantime, I will provide several updates of core components migrated to Swift, along with some refactors and cleaning. The first iteration should land soon with most non-UI code migrated to Swift and all dead code removed, probably as version 3.1 requiring iOS 13.

The Swift<>Objective-C Bridges

There has been some hickups along the way of this first update. I had to learn how to allow communication between Objective-C and Swift possible.

You need to create some a bridging header file that will expose your Objective-C classes to the Swift code space.

//  Use this file to import your target's public headers that you would like to expose to Swift.
#import "Kana_no_NihongoAppDelegate.h"

This file needs to be assigned to the Objective-C Bridging Header build setting of your project and contains references to your Objective-C headers.

Objective-C Bridging Header Build Setting Objective-C Bridging Header Build Setting

And if you need some of your Swift methods or classes to be exposed to Objective-C, you need to use the @objc or @class attributes.

@objc(KanaItemRepository)
class KanaItemRepository: NSObject, XMLParserDelegate
{
    ...

    @objc
    class func prepare(withManagedObjectContext managedObjectContext: NSManagedObjectContext) {
        ...
    }

    @objc(refreshStats:)
    func refreshStats(notification: Notification?) {
        ...
    }
}

Beyond that, there is only a few things that are done differently between the languages (like how to iterate over an array), but most of the code has been a direct translation.

The Next Step

Before stepping into the dangerous UI redesign territory, I will have to remove the deprecation issues related to CoreData and probably move the app to an up-to-date implementation of CloudKit. This will be discussed in a future post as the process presents its own challenges.