Dec 1, 2014

Why I think Swift is not ready yet




UPDATE Feb '15: With Xcode 6.3, Apple fixed some of the issues this post is talking about. However - there are still some major issues for me, the number one of them is the fact I can't use Swift classes in Objective-C without porting the tests for them to Swift.

So,
Like every relatively-early-adpoter-iOS-developer, I decided to give Swift a try in the past few features I worked on for Piano Maestro.

It was a lot of fun to get into, and I wrote some pretty code and features came out very nice. However, I ran into some issues, that made me eventually come to the conclusion that swift isn't quite ready yet, and I should stick to Objective-C as the main language for developing iOS apps. At least for now.

Here are my top reasons:

Inaccuracies in compilation errors
Often, when a line is relatively complex and has a compilation error, compiler will give you an error message that's simply not describing the real issue.

The most common use case is a simple error like sending the wrong primitive type as an argument to a function (a problem that happens a lot to us Objective-C/C/C++ developers, which are used to implicit conversion of primitives).

Consider the following example:
WAT??
dispatch_after receives exactly these types arguments. So what's wrong here?

Turns out the problem is that dispatch_time expects Int64 to be sent as the second argument, and I actually sent NSTimeInterval.
But how could I know that from that irrelevant error message?

There went an hour of banging my head until I figured this out.


UPDATE Feb '15: at least for this example, was fixed in Xcode 6.3 Beta 1 and error message is now very descriptive and relevant.




Debugging is hard
More head banging often happened when trying to see the value of a variable in the debugger, I eventually find myself adding debug prints instead.
A tip about this: If you get "Some" as the output of trying to 'po var', you can 'po print(var)' instead, and it will (hopefully) work.


Can't use Swift code within Objective-C in unit tests
Update May 2015: I found workaround!

While it's absolutely possible to mix Swift <-> Objective-C code in the app's main target (apart for some limitations I will rant about later), in the test target, I can't import $(PRODUCT_MODULE_NAME)-Swift.h in Objective-C code.
This does not only mean that tests for Swift classes can only be written in Swift (fair enough), it also means that any Objective-C code in my app that uses Swift classes cannot be tested at all. Build will fail if it's included in the test target of the project.
LAME.

See:

Can't use tuples and trivial enums in Objective-C
As the official documentation says, you can't use Swift-only features in your Objective-C code.
This makes sense for some things, but it would make a huge difference if they could have made an effort to expose some of the more trivial features in the $(PRODUCT_MODULE_NAME)-Swift.h bridge:
- Trivial enums can become C enums with a prefix (like it's done in the opposite direction)
- Tuples can become trivial classes
etc.
For now, I can't expose functions that receive a tuple or a Swift enum to Objective-C, and must add some kind of bridge myself (e.g. get an Int parameter instead of an enum and use the constructor with rawValue:). 
Maybe it was too much of an effort for Apple to deal with, but this makes it harder to use these features if I know the class will be used in Objective-C code.

UPDATE Feb '15: you can now use trivial enums!

Can't use c++ in Swift
If like us, your app uses Objective-C++ code and not only Objective-C, you're in trouble and won't be able to use any code that uses c++ types in the header. You'll have to create some kind of Objective-C bridge that will hide the c++ types.


Can't use mocking frameworks
Because of limitations in the availability of the language runtime in Swift, there's no good way to use a mocking framework for tests right now. That's a big problem.
In the meanwhile - best workaround IMO is adding an Inner Class called "MockMyClass" in your test, and overriding any methods you want to mock (like we did in 2006 before mocking frameworks were introduced).

See:

Xcode sucks, AppCode has only limited support
So, as you probably know from my Xcode vs AppCode comparison (a bit outdated, but most of it still applies), I don't use Xcode for coding. It's lacking some very basic IDE mechanisms that AppCode is excellent at (e.g. Extract Method, Quick Fix, Find Usages, ...).
This is still true for Xcode 6.1 and Swift support. Sure, Xcode improved since writing this comparison, but still - I can't even extract method? This sucks.
Unfortunately, Swift support in AppCode is still very rudimentary. But the good news is that they are working on it.
In the meanwhile, here's a link to AppCode EAP that contains some basic features of syntax highlighting and some basic refactoring in Swift. I still don't recommend it over Xcode's current Swift support though.

UPDATE Feb '15: AppCode 3.x has basic Swift support, but still has a very long way to go in order to be as good as it is for Objective-C in terms of refactoring etc.

To sum it up

I guess things are not that bad, because Swift is a very neat language and has some really cool features I'm in love with, like tuples, better enums, cooler closures, generics, property observers, and many many more. 
I assume my complaints are either going to be solved soon, or become less of an issue - many of them are mix&match issues, which only affect apps with existing Objective-C/C++ code. Hopefully

Anyhow, at least for the time being, I guess I'll stick with Objective-C as the main iOS development language.

Further reading:
Developing a Bidding Kiosk for iOS in Swift - a great retrospective with some more reasons of why Swift isn't ready yet.