10 min read
Since its launch, many iOS developers have been struggling with the question of if, how, and when to transition from Objective-C to Swift. The answer to that question will of course be different for every team and every project.
There are a number articles you can read covering many of the advantages of Swift. So instead of rehashing those same points, in this article we’ll instead focus on some of the concerns you may want to consider before learning app development with Swift.
But first, let’s turn the clock back a bit…
Before Swift: You will use Objective-C, and you will like it…
The year was 2010. The iPhone was not yet 3 years old, and the ability to write native apps for the iPhone had only been around for about 2 years. On April 8th of that year, Apple announced version of the iPhone OS. The iPhone OS (this was before it changed its name to iOS) included such tantalizing new features as multitasking, fast app switching, and background services. Understandably, iPhone developers were eager to get their hands on the new SDK and start playing with all those exciting new features.
But the iPhone OS 4 SDK contained an unexpected bombshell. This bombshell wasn’t in the software, it was in the usage agreement. With iPhone OS 4 SDK, Section 3.3.1 of the Developer Agreement was updated to include the following troubling language:
“Applications must be originally written in Objective-C, C, C++ … and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs.”
– Section 3.3.1 of the iPhone OS 4 SDK Developer Agreement
Needless to say, this new restriction caught many developers by surprise. The official reason for the change, provided by Steve Jobs himself, was to prevent the usage of cross-platform tools such as the recently announced Flash CS5. Jobs was quoted as saying that “intermediate layers between the platform and the developer ultimately produces [sic] sub-standard apps”. But the fact that Apple’s approach to combating these “intermediate layers” was to restrict what programming languages could be used to write iPhone apps revealed something more about Apple’s thinking: Objective-C should be good enough for anyone.
One could be forgiven for agreeing with this assertion, as Objective-C won the Tiobe Index’s “Programming Language of the Year” award two years in a row. But the reality was that Objective-C’s popularity was a function of the growing app ecosystem, and not the other way around. Even back in 2010, many people were already dissatisfied with Objective-C and, as a result, alternative ways to write iPhone apps in other programming languages were already cropping up.
Eventually, under pressure from the developer community at large, Apple rescinded these changes to Section 3.3.1 of the SDK Developer Agreement just five months later. Still, the message was clear: if you wanted to write apps for the iPhone, you should probably be using Objective-C.
… or maybe not. Enter the new iOS language Swift.
Fast forward 4 years from that incident to June of 2014 when Apple introduced developers to its new language, Swift. If the message of 4 years prior was that Apple was perfectly satisfied with Objective-C, then the message sent by Swift’s introduction was that Apple was finally ready to admit the truth. Objective-C might not necessarily be the best language for writing mobile apps.
Much has been said about how Swift is a more “modern” language than Objective-C. If you’re interested in how to learn the Swift programming language, you might want to check out the guide for moving from Objective-C to Swift.
What you should notice, though, is that there are two important differences between the Objective-C and Swift languages:
- Swift is not a strict superset of the C language.
- Swift is statically typed, not dynamically typed.
Not being a strict superset of C means that Swift is free to make use of syntax constructs that would otherwise not be allowed. This makes it possible, for example, to implement custom operators in Swift.
Being statically typed means that Swift can take advantage of many of the recent advances in type systems pioneered by languages such as Haskell.
Despite having been in development for 4 years before being revealed to the public, Swift is still a young programming language, so it comes with a number of caveats.
Compatibility with Objective-C
iOS shares a common heritage with OS X, which in turn takes its history from the NeXTSTEP operating system first released in 1989. NeXTSTEP was originally written largely in Objective-C, and many of the core libraries in OS X and iOS trace their roots all the way back to these original implementations. (Incidentally, this is where the ubiquitous “NS” prefix found on core classes such as
NSString comes from.) While Swift could theoretically exist in the absence of theses core libraries, the reality is that any Swift programs you might write in the near future will have to interface with Objective-C.
To their credit, the developers behind Swift have done a fantastic job making interaction with existing Objective-C libraries as painless as possible. That is not to say that the process is completely pain free though. Apple has provided a helpful guide explaining how to call Objective-C code from Swift, and vice versa, but there are some important impedance mismatches to be aware of.
Perhaps the most obvious mismatch relates to header files. Objective-C, owing to it’s C roots, still requires that functions be declared before being called. When calling out to a library, these declarations will be found in the library’s header files. Swift, however, does not use header files. So, if you want to call Swift code from Objective-C, you will first need to create a “bridging header”. While conceptually this may not seem that complex, in practice, it actually can be quite the task.
Another set of complications in interfacing between Swift and Objective-C stems from the inherent differences in their type systems. Swift, taking a cue from other modern languages, has done away with the concept of
nil. In its place are Swift’s optional types. For example, a method that opens a file only if it already exists would have a return type of
File? (instead of just
File) in Swift. By tracking all the places where types are optional, the Swift compiler can effectively make it impossible to encounter the dreaded “Null Pointer Error”. That is, of course, unless you’re calling Objective-C. Since Objective-C makes no such guarantees about not returning
nil, Swift has a special category of types called Implicitly Unwrapped Optionals that are used when calling Objective-C code. These types can be treated as optionals in the Swift language, along with all the accompanying overhead required for existence checking. Alternatively, they can be used the same as any non-optional type, but if Objective-C does return a
nil you will end up with a runtime error, so you lose some of Swift’s compile-time safety guarantees.
Finally, a slightly more subtle mismatch to consider when programming in between Swift and Objective-C has to do with how objects and classes are created under-the-covers in these two languages. Objective-C, owing to its dynamic nature, utilizes dynamic dispatch to call methods on objects (via
objc_msgSend). Swift certainly can use dynamic dispatch, but since it is statically typed it also has the option of using a
vtable to store function pointers for each method. Which of these two mechanisms Swift uses depends on a couple of factors. Plane Old Swift Objects will use the
vtable mechanism, unless the class or methods within the class are annotated using the
@objc Swift attribute. Swift classes that inherit from Objective-C classes will use dynamic dispatch for inherited methods, but not for any new methods introduced by the subclass (though, again, you can force the use of dynamic dispatch with the
@objc attribute). Regardless, Swift code will always be able to work with Swift classes, but Objective-C code can only utilize Swift objects and methods that have been properly annotated.
Faster than Objective-C?
When Apple introduced its launch, one of the benefits of Swift that was especially emphasized was its speed. This is understandable when you consider that one reason often given for Apple’s reluctance to switch away from Objective-C to a higher-level language was that Objective-C, being essentially an extension to C, was capable of creating much faster, more efficient programs than something like Python or Ruby. Even so, Objective-C is no rocket ship when it comes to absolute performance, and much of that can be attributed to dynamic typing. So with Swift adopting a static type system, one would expect that Swift should be at least as fast, or faster, than Objective-C.
Of course, as the saying goes, “There are three types of lies: lies, damned lies, and benchmarks.” (Or something like that…) Certainly, there are numerous reasons why the Swift language might run faster. Unfortunately, it seems that the way Swift utilizes Apple’s ARC (Automatic Reference Counting) technique for memory management sometimes results in Swift’s compiler generating significantly slower programs, especially with lower optimization settings (such as what you might use during development). The good news is that it seems like improvements to Swift are continually addressing this issue, and it’s therefore likely that in the near future Swift will generate executables at least as fast, or faster, than Objective-C.
There’s another caveat to the speed of Swift, though. The whole point of Swift is that developers won’t be writing the same code that they would have been writing in Objective-C. What does this mean for performance? Well, certainly it means that comparing performance between Swift and Objective-C is more involved than simple benchmarks can reveal. It also means that comparing the absolute runtime performance of generated executables only tells half the story.
Everyone wants fast programs, but oftentimes development speed is as – if not more – important. A language that is more expressive, able to accomplish more work in fewer lines of code, can be a huge benefit in this regard. On the other hand, when working in a compiled language where the edit-compile-run-debug cycle occupies much of a programmer’s day, a slow compiler can really hurt productivity. While the evidence is primarily anecdotal, it does seem that the Swift compiler is currently just slow enough to be annoying, especially when working with code that exercises Swift’s advanced type-system. One group even found compilation speed to be problematic enough to motivate a switch back to Objective-C.
Speaking of the Swift compiler, it is itself the source of even more caveats when considering making the switch to the new Swift language. Aside from compilation speed, as Swift has emerged from the small cadre of developers working with it at Apple and been unleashed on the masses, the compiler has started to show cracks under the stress. There is even an entire GitHub repository dedicated to collecting examples of code that will cause the Swift compiler to crash.
There is also the question of how the Swift compiler will change. Another project on GitHub is collecting speculation and analysis from the community on what changes might be in store for Swift. For example, custom operators can place significant strain on a parser. Initially, custom operators in Swift could not use a question mark (?) character. While this has been fixed in the latest Swift release, requests continue to stream in from the growing community of Swift developers for even more flexibility in what can be considered a valid custom operator.
Any time you hear that the parser for a language is in flux, it should give you pause. A language’s parser is the heart and soul of a programming language. Before any language semantics can be applied to impart meaning on code, it’s the parser that determines what is and isn’t valid code to begin with. It is encouraging, then, that Apple has promised to ensure some level of runtime compatibility for Swift. That does not necessarily guarantee, though, that Swift code will run without being recompiled for each new release of Xcode and/or iOS. Nor does it guarantee that you won’t need to rewrite portions of your Swift code to remain compatible with future releases of Swift. But again, Apple’s commitment to make this process as painless as possible is at least some small solace.
Some of the worst programming languages ever created (which shall remain nameless) have been buoyed along, long after common-sense says they should have been relegated to the dust-bin of failed technology by the strength of their respective communities alone. At the same time, the collection of really nice programming languages that have failed to take hold for want of a community are too numerous to count. Strong communities produce tutorials, answer questions on Stack Overflow, hang out online or in person at conferences sharing stories, tips, and tricks, and write and share useful libraries with each other. When choosing what language to use for a project, community is definitely something to consider.
Sadly, the iOS/Objective-C community does not have the best reputation for being friendly and welcoming. That is gradually changing, and open source is increasingly playing a more important role in Objective-C development. Still, at this early stage it’s hard to tell what the Swift community will look like going forward. Will it consist mostly of insular developers working only off of the official Apple APIs and their own private collections of code? Or will it be a vibrant community of groups sharing tips, tricks, and useful libraries?
Another facet of the role of community is the role of Swift’s developers themselves. The overall trend in programming has been to move away from proprietary programming languages and platforms to open source solutions. Open Source development, especially at the level of programming languages and runtimes, can be a real advantage. While the Swift developers have stated multiple times that their intention is to completely open source the Swift language and runtime, that has yet to occur so caution is warranted.
That said, the developers behind Swift are some of the same developers behind the long-running LLVM project. LLVM is not a perfect analogy, since it started life in the open as a project out of the University of Illinois, Urbana-Champaign. But to their credit, the core developers have remained very open and engaging with the community, even after most of them transitioned to working for Apple. It is completely reasonable to expect that the Swift language will continue to be developed (mostly) in the open, though whether or not patches and feature suggestions from the community will ever make their way into the language remains to be seen.
Should I Learn Swift?
There is, of course, no “one size fits all” answer here. As always, choosing the right tool for the job requires intimate knowledge of all the details of the project in question. Certainly, at this point in time, Objective-C remains the “safe” choice for iOS development, but Swift is definitely worthy of consideration.
The most significant change that Swift brings to iOS development, though, is that many developers will, for the first time, be asking themselves the question: “What language should I use?” Given the history of Apple, Objective-C, and the iOS platform, this change alone is rather exciting, especially considering that the choice is not binary. While Apple has made clear their preference, the iOS developer community at large has been hard at work for years already providing even more possible answers to this question.