For the past few days I’ve been confronting the awful truth - That Swift and Objective-C really don’t play well. It started some time ago. I have a DI frame written in Objective-C called Alchemic which works very well for Objective-C projects. With Swift gaining traction in the workplace I looked to enable Swift support.
It turned out to be not that hard. All I had to do was to write a few Swift functions to replicate functionality that I had wrapped up in pre-processor macros to simply using the framework.
So far, a simple update and things looked good. This week though, I’ve attempted to use it for the first time in a real 100% Swift project and it’s failed to make the grade.
The problem I encountered boiled down to one core issue. To be able to use Swift types in Objective-C, you have to effectively convert them to Objective-C types. Mostly this consists of inheriting from
NSObject or using Swift’s
@objc qualifier to tell it to use make things Objective-C friendly.
Whilst this worked, it mostly felt dirty, like I was doing something wrong. However the real problems started to occur when I need to use types that don’t translate to Objective-C. In my case - enums with associated values. Something completely impossible to translate into Objective-C.
So I was left with a choice - either drop the DI framework or stop using Swift only constructs such as non-numeric enums, structs and various other types.
I’ll be honest here, I’m no fan of Swift’s structs so that wasn’t really an issues because I avoid them to start with. But I needed some of the others.
Luckily for me I found a Swift based DI framework called SWinject that works in a way I like, is 100% Swift and has most of the features I want from a DI framework. The one or two I would like it to have would mean dipping back into the Objective-C runtime and as a result, would cause Objective-C constructs to start trickling back into the Swift code.
After working with Swinject for a couple of days I’ve decided I quite like the way it works. It’s made me think about some of the design aspects of Alchemic and I’m wondering if I should reconsider some of them. But with the emphasis on Swift becoming the dominant language for he Apple ecosystem, I’m more inclined to leave Alchemic design as it is and use Swinject for Swift projects. Although Alchemic’s still the best framework for Objective-C IMHO.
So whats this article about then? Well… mostly about my mixed feelings on the subject. The experience has made me realise that’s whilst is plenty of interoperability between the two runtimes, there is a significant amount of difference as well. In short, I’m now recommending to avoid mixed code bases wherever possible. It’s bad enough dealing with design issues in one runtime, never mind having to deal with two and the border between them.
So what to work with in the future. There’s no doubt in my mind that Swift is the direction everyone is going with. Compared to Objective-C there are things I like about it and things I don’t. It’s easier to write than Objective-C, often easier to understand for those with less coding under their belts and has a number of modern language features. On the other side I don’t like the bastardisation of structs, tuples that are really just glorified dictionaries, the difficultly of clear interfaces without using protocols, and the constant optional wrangling.
So unless you need Objective-C’s advanced runtime features, I’d go with Swift despite my preferences. For me, I’ll be using it in my future projects simply because I think it’s time to move on.