6 Ways Swift Improves On Objective-C

Swift2

At Atomic Object’s Ann Arbor office, we made it a point to watch the 2014 WWDC keynotes, and it’s not an exaggeration to say our jaws were on the floor when Swift was announced. With Swift, Apple is moving forward with a much more modern programming language, and I am excited to get in on the ground floor and start developing with it.

In this blog post, I will highlight a few language features in Swift that will make developers’ lives easier.

Issues With Objective-C

When a new candidate for a developer position applies at Atomic Object, we give them a Getting To Know You (GTKY) document to fill out. The document asks a number of general questions, technical and otherwise, including, “What is your favorite language, and what would you do to improve it?” This question generates a surprising number of fails, one in particular was when a developer chose Objective-C as their favorite language and could not think of a single improvement to it!

This answer generated a lot of discussion and made me think about issues I have with Objective-C. To name a few:

  • Weak typing — often dealing with id or Class, and the need for awful C static casts.
  • Poor enumeration syntax — for in is nice enough, but I often also want an index as well.
  • Lack of operator overloading on classes such as NSNumber.

So, I was delighted when Apple announced Swift and language details came to light. I will touch on a few here that address many of my complaints with Objective-C. I strongly recommend developers to download the Swift programming Language book and take a look at the Xcode 6 beta.

Exciting Features of Swift

1. Type Inference

This is a huge one for me. Beyond the annoyance of having to (unsafely) cast instances of type id to the actual type, it’s very easy to make a mistake and send a signal to an id that the actual object does not respond to. Always checking respondsToSelector is very tedious. One solution Swift gives us is the var keyword:

1> var anInt = 0
  anInt: Int = 0
2> var aDouble = 0.0
  aDouble: Double = 0
3> var anotherDouble: Double = 0
  anotherDouble: Double = 0
4> var aString = "some string"
  aString: String = "some string"

Note that you can also explicitly set the type, as in the anotherDouble case. Types can be inferred for constant values using let in the same manner as var.

2. Improved Enumeration Syntax

Objective-C has a nice syntax for easy collection enumeration:

for (SomeType someObject in array)
    NSLog(@"%@", someObject.whatever);

That is a nice bit of syntactic sugar, but the problem is that very often in real-world programming, I need an index variable alongside the object instance from the collection.

Swift gives us a lot of useful collection enumerators, but I’m especially happy that they provided a global enumerate() method that returns a tuple for each item in the array composted of the index and value for the item.

19> array
$R2: String[] = size=4 {
  [0] = "one"
  [1] = "two"
  [2] = "three"
  [3] = "four"
}
20> for (index, value) in enumerate(array) {
21.     println("Item \(index): \(value)")
22. }   
  Item 0: one
  Item 1: two
  Item 2: three
  Item 3: four
23> 

3. The Override Keyword

When declaring instance functions in a class, if they override a base class function, they must be marked with the override keyword. Failure to do so results in a compile time error. Similarly, marking a function as override that does not override a base class function also results in a compiler error. This behavior will make classes more clear and less prone to runtime crashes.

4. Multiple Return Values

In the job I had before joining Atomic, I was primarily working in C++, and I often found myself writing methods whose output was multiple values. I struggled with the decision to pass in multiple ‘output’ arguments by reference, use pair, or wrap the return values in a struct or class.

In Swift, there is a built in mechanism for what amounts to returning a tuple with an arbitrary number of labeled data members.

46> func calculateStatisticsFromArray(data: Double[]) -> (mean: Double, median: Double, mode: Double) {
47.          return (62, 44, 12)
48. }   
49> var stats = calculateStatisticsFromArray([])
stats: (mean: Double, median: Double, mode: Double) = {
  mean = 62
  median = 44
  mode = 12
}
50> stats.mean
  $R10: Double = 62
51> stats.median
  $R11: Double = 44
52> stats.mode
  $R12: Double = 12

Swift also supports declaring a number of vars and getting the return value into each explicitly:

<51> var(mean, median, mode) = calculateStatisticsFromArray(data)

5. willSet, didSet

In Swift, classes have properties (similar to Objective-C). There is a mechanism for declaring setters and getters, but if the type of the property is simple and needs to computation, but you want to observe when it is accessed, there are two built in methods to override- willSet and didSet.

1> class Container {
2.     var someValue: Double = 0.0 {
3.         willSet {
4.             println("willSet! \(newValue)") 
5.         }
6.         didSet {
7.             println("didSet! \(someValue)")
8.         }
9.     }
10. }

11> var c = Container()
  c: Container = {
    someValue = 0
  }
12> c.someValue = 100.0
  willSet! 100.0
  didSet! 100.0

6. The REPL

REPL stands for “read-evaluate-print-loop,” and I think of it as a sandbox to for testing out code. You can type code into the REPL as if you’re in an IDE or your favorite text editor, and it will be compiled/interpreted and run in real time- allowing you to see the output right away. This is a great feature for a developer trying to learn a new language. I’ve been using it to learn Swift.

To use the Swift REPL:

  1. Download the Xcode 6 Beta.
  2. In terminal, run the following command to switch the PATH for xcrun: sudo xcode-select -switch /Applications/Xcode6-Beta.app/Contents/Developer. Note: to reset this, use xcode-select -r from the terminal.
  3. xcrun swift

What Does the Future Hold?

I strongly believe that, in iOS 8 and beyond, Swift will grow to become the dominant language in iOS development. That said, Apple has assured us that the runtime will remain binary compatible: our Objective-C apps will continue to work. It is also clear that Swift syntax and semantics will change post-iOS-8. Apple told us that they will not guarantee source compatibility, but will provide code converters. While the thought of running a converter on production code scares me a little, I think the time to move to Swift will come sooner (iOS 8-9 timeframe) rather than later.
 

Conversation
  • Alex says:

    Language is a tool, nothing more. So your screwdriver is a little shinier or your hammer a little heavier. When an interviewer asks me “what’s my favorite language”, I know they’re not a real engineer and their priorities will shift with the wind.

  • Carl says:

    Hi John… check out block enumeration in Obj-C, that gives an index, you can also enumerate backwards as well :)

    • John Fisher John Fisher says:

      Carl, thanks for the useful tip- you’re right I overlooked the block enumeration syntax.

  • Mike says:

    Two of the “issues” you have have with Objective-C are features to those who have come to love the language. Which leaves the asinine enumeration issue.

    Weak typing is awesome! Sure, casting *from* id is sometimes a nuisance, but casting *to* id is a godsend. Rather than having to type out a large cast such as (ThreeLinesWithAnImageTableViewCell*) you just type (id). It happens automatically because the compiler loves and trusts you.

    Operator overloading is syntactic sugar that forces the developer to understand inner nuances of a class before even doing or reading simple code. When common operators (like ==) mean different things to different objects, your language is fundamentally broken.

    I like your follow-up question, though. If I do interviews again in the future, I’ll have to steal that.

    FWIW – Swift does solve some of my personal gripes with Objc, but they are mostly things that arise with other developers’ coding habits. Swift makes it easier to not write fundamentally broken code – which is great when you work with many other people of varying skill levels. Admittedly, Objective-C is very much a language whose quality sometimes relies too much on coding conventions.

  • c says:

    weak typing is not a blessing..
    a little set theory should demonstrate that..
    it all resolves to a question of which is easier to manually check (in general) or even reason about. a smaller compile time set or a larger runtime set.
    we all know the answer to that.
    in addition insulation, invariants and object hierarchy are poorly supported in “objective-c”.
    all in all it is a mess and from what i have seen is not suitable for LARGE-scale projects. and is a mess for smaller ones.
    and that’s before we even consider the sub-standard IDE.

  • Comments are closed.