A few months ago myself and 5 other developers started a brand new project for one of our clients. We decided to use Apple's Swift language instead of Objective-C as both the client and ourselves were interested to see how well it worked. After 3 months of complex UIs, networking, and all the stuff that goes with an enterprise level app, I’ve decided it’s time to talk about my thoughts on using Swift on something other than an app store toy. So here goes :-)
Things I like about Swift
- Custom operators - They give me the ability to expand common operators so they work on types other than those Apple provide. I can also define completely new operators to handle functionality that would be better expressed as an operator than a function. Recommendation, use with restraint.
- Protocol extensions - Objective-C has a similar functionality via categories, but protocol extensions allow me to define functionality and apply it to anything I like without there being any specific type involved. They are a good way to encourage the use of protocols and programming to them. Wish we had them in Objective-C.
- Enhancements to switch statements - Although I’ve not used them much, they are much more powerful than the simple C versions in Objective-C.
Things I’m pretty much Meh! about
- Tuples - Some people get really excited by these and they are handy for easily returning multiple values from a function or storing things sometimes. But I can just as easily use an array/ dictionary, struct, class etc. So far, named or unnamed, I’ve not really seen anything that would make me either like or dislike them especially.
- If-let… and guard - These two are really just fancy if statements that feel like bandaids on the mess created by optionals (see below). Swift would be much better off without them, simpler to learn and understand.
- Enums as classes - The pros are that you can add functions to them so they can do a lot more than just be used in expressions. The cons are that they are no longer just integers, so a fair amount of converting raw values to and from them creeps into the code. Plus creating and using enum based binary flags is no where near as easy as with Objective-C.
Things I don’t like about Swift
- The Optional implementation - Although I understand the reasoning for what Apple's done, I find Optionals to be intrusive, both in the code and with the constant interruptions to my thought processes. They are a regular source of much angst in the team and generally not liked much. Often, the compiler is simply too aggressive in dealing with them, forcing developers to write code they simply don’t need to handle situations that won't occur. I’m sure Apple could have achieved the same goals in a simpler fashion.
- Structs - They are present in Objective-C, but dumb, simple data structures. Swift has "Frankenstiened" them into half baked classes by allowing functions and protocols to be applied like they were classes. They are not compatible with Apple’s APIs such as UIKit and cannot be used anywhere you need to access Objective C based code. Sure they get don’t get passed around by reference which can stop 'some' bugs, but any half decent developer will have no problem dealing with those anyway. Finally the emphasis being placed on them by some people as a replacement for classes is a bad idea. Use them sparingly.
- Generics - I like using generics for collections and the few classes where I can actually make use of them. But not being able to use them with protocols heavily limits their usefulness. Especially given the protocol driven approach that Apple seems to be supporting. Apple needs to fix this to make them as useful as they are in other languages like Java.
- Using type aliases to make protocols generic - Really bad idea. The protocols can no longer being used as a generic type in collections or set on classes, which is perhaps one of it’s most useful attributes. About the only thing you can do with them is define other protocols.
- Functions acting like closures - I like blocks/closures and use them a lot. They solve a lot of asynchronous problems and are useful in strategy patterns. However Swift has implemented all class and struct functions as closures. i.e. if you pass a function to another piece of code, it acts exactly like a closure, retaining self and referenced data. I would have not done this. A function should be able to be called on an object of the relevant type. Similar to how IMPs work in the Objective-C runtime. When you call them, you give them the object to work with. Making functions work and look exactly like closures just complicates and confuses things, especially for new developers. If Apple wanted to make them work this way, they should have unified closures and functions as one thing.
- Compile time binding - Might make the code fractionally faster. But really cripples runtime access and even Apple has admitted it’s caused issues with attempting to apply generics to protocols.
- Lack of the preprocessor - A lot of people don’t like the preprocessor, especially preprocessor macros. But it's a very useful thing if used carefully.
- Replacing common runtime classes with structs - NSString (Objective-C class) and String (Swift struct) for example. Sure, Apple has built in functionality to seamlessly convert back and forth, but by going with structs, Apple has made it very hard for third party APIs that want to provide functionality written in Objective-C to use Swift. Mostly because Objective-C does not understand Swift structs.
- @objc to tell Swift to make something Objective-C compatible - Almost useful when you have to deal with Objective-C APIs. However there is a fair amount of recommendations around the web to tag stuff with this in order to gain Objective-C functionality. Really? Why not just write Objective-C then?
- XCode - Not truely a Swift issue, but XCode with Swift is quite unstable. Dozens of crashes a day is not unusual. Further I've found that when using externally built frameworks (we are using carthage) Swift will put some sort of lock on the framework file, causing XCode to crash and resulting in the framework files having to be rebuilt even though they've not been changed in the slightest. XCode also has a great deal of issues with Swift errors, code completion various issues only clearable by wiping the derived data path.
Is Swift the way of the future? Some people love to make grand pronoucements like this. but the fact is that Swift is nothing more than another language. Not any better or any worse than dozens of other languages. Mostly when people talk about this sort of stuff they are really talking about things other than the language, the APIs it uses for example, or design patterns, etc. So I don't see it as anything innovative.
Would I use Swift again? Short answer is No. There is simply nothing in it that I would regard as being so much better than Objective-C that I would consider it. And so far, my experience is that I find the day to day coding in it not as smooth or enjoyable as working with Objective-C.
Would I recommend Swift as a language for learners? I don’t think Swift's any easier for a beginner to pick up than Objective-C. Sure, Apple have made some things simpler in terms of dropping header files, removing pointers and some C like syntax. But they've made it harder and more frustrating with things like Optionals, If-Lets, etc. So it actually doesn’t matter which language you choose - Objective-C or Swift, you are still going to have to learn about the same amount of stuff. It's just that each language has a different set of issues. Apart from that, they both have to spend a lot of time access the same APIs and that's where the real learning is.
Would I re-write an Objective-C API is swift? Some third party APIs I've seen have done this, or used a move to Swift as an excuse to re-write their cores. Unless there was a really compelling reason to do so, I would not make this change as there is nothing to be gained from a language or functionality point of view.