Moving from Android to iOS development

Until recently I’ve mostly been working on the Android app for our client PostNL (the premier provider of postal and parcel services in the Netherlands). 3 months back I switched to iOS development. Here’s what I’ve learned.

The good

Speed

Building and running iOS applications is much faster compared to Android. Sometimes building can take a long time, but mostly when making small changes and re-running the app in the simulator it just takes a couple of seconds.

Hopefully the announced Android Studio 2 will fix some of these performance issues for Android.

Passing data around

In Android you have Activities (and, even worse, Fragments) with their complex life cycles. Passing data around (for example when starting a new activity) is cumbersome. You need to attach data to an Intent as Parcelable or Serializable. This can get tricky, especially if you have complex models.

On iOS, this is much easier: either your app lives, or it doesn’t. Data stored in fields in controllers will not disappear. You can get direct references to new controllers, so you can pass data around in a type-safe manner. Hurray!

Swift 2

One of the best things about iOS development compared to Android development is the programming language. Swift is better in so many ways compared to Java. Learning Swift coming from Java went pretty quickly. What really helped me was that I could dive into an existing code-base with many similarities to the Android app. Some of the things I love the most about Swift:

Swift 2 — Optionals

Optionals really help to prevent those dreaded NullPointerException’s you might be familiar with in Android. In Swift you simply cannot accidentally reference a variable that is nil (Swift’s variant of null).

Optional chaining lets you write code that’s much less verbose than Java, for example:

if(foo != null && foo.bar != null && foo.bar.baz != null) {
  foo.bar.baz.doSomething();
}

VS

foo?.bar?.baz?.doSomething()

Swift 2 — Immutability and pass by value

I’ve always preferred working with immutable objects as much as possible. They make life simpler and reduce the chance of bugs. In Java it’s next to impossible to use immutable objects. Swift offers powerful tools like structs, enums and the let keyword to work with immutables. This, combined with the fact that most types (except classes, so I use structs in favour of classes when possible) are passed by value instead of reference, will result in code that is less prone to errors.

Swift 2 — Functional programming

Using functional concepts like map, filter, and reduce is a breeze in Swift. Combined with the “trailing closure” syntax, it delivers clean and compact code:

[1.3, 4.5, 6.8, 10.5, 15]
.filter { $0

For the Android app, we use Retrolambda and a Backport of the Java 8 java.util.stream API to provide similar code, but’s it’s not as elegant as Swift.

Swift 2 — Extensions

With extensions, you can add new functionality to an existing class, struct, enum or protocol (interface). This is useful for a variety of reasons, for example to get rid of those StringUtils or WhateverUtils classes in Java. In Swift you can simply add functions to, for example, Strings.

You can even implement your own operators in Swift or use subscripts for extending the functionality of collections. For example, we added the following subscript to allow for index-safe get`s from arrays:

extension Array {
  subscript (safe index: Int) -> Element? {
    return indices ~= index ? self[index] : nil
  }
}

let numbers = [1,2,3,4,5]
// Returns optional instead of failing when providing an invalid index
let number: Int? = numbers[safe: 6]

The bad

Autolayout

Alright, let’s get the air cleared here, I wouldn’t want to call AutoLayout “Bad”. It’s a very powerful layout system with many, many features. In my experience, AutoLayout has a pretty steep learning curve. I’ve spent many hours playing with constraints to get the desired result and resolving conflicts.

Additionally, if you’re dynamically hiding views in code for Android, the layout will automatically be adjusted and the surrounding view will be displayed in the correct position. If you want the same behaviour in iOS, you’ll need to create outlets for the relevant constraints and adjust them manually, again increasing complexity.

For most mobile screens, I’m faster designing them in Android’s XML layout compared to using AutoLayout, but maybe I need some more time getting familiar with AutoLayout. :)

The new UIStackView might ease some of my AutoLayout pains, but for now we can’t use it because we need to support iOS 8.

CoreData

I’m not really a CoreData expert, so maybe I’m not allowed to complain, but I’m gonna do it anyway. My first encounter with CoreData wasn’t a great one. Again, CoreData is a powerful persistency framework with lots of features. But it felt very cumbersome to modify and retrieve data for a relatively simple data model. We have already been looking at some alternatives like Realm, which we might be using for our next project.

Xcode

Xcode as an IDE just isn’t as mature as Android Studio. It’s missing many features and it doesn’t have the most intuitive user interface. Here are some of the things I dislike about Xcode:

  • Code completion just isn’t nearly as good as Android Studio’s
  • Limited tools for navigating through code (jumping to implementations, finding usages, etc)
  • No code analysis tools (finding unused code, etc)
  • No refactoring tools for Swift
  • The way Xcode organizes files, which doesn’t correspond with the filesystem
  • Connecting outlets and actions for UI Components by dragging feels cumbersome

The ugly

Learning AutoLayout is one thing, but Xcode crashing 50 times a day (mostly when editing storyboards) really made me pull my hair out…

Additionally, sometimes when writing complex pieces of code (with lots of chained methods), the compiler just crashed, also disabling code completion and syntax highlighting in Xcode… This left me inspecting compiler crash logs and commenting out code piece by piece to see what was wrong. Swift is still a very young language, so these issues will probably be addressed in the near future.

Conclusion

I personally still enjoy writing Android apps¹. It’s not like I’ve never wanted to go back to Android during the last couple of months of iOS development. But using Swift 2 for creating iOS apps is undeniably a pleasure. Okay, Xcode is still a little rough around the edges, but this will hopefully improve in the future.

Recently, Apple opensourced Swift, which will lead to a thriving community, bringing Swift to the next level and resulting in many more great libraries we can use when developing iOS apps.

¹ Especially when using the right tools like Retrolambda, RxJava, RxPromise and Backport of the Java 8 java.util.stream API, which makes working with the outdated Java 7 much better.

We have also been playing around with Scala for Android which addresses most of the language issues we have with Java, Maybe we should give this a try for a next project.


Check out our Engineering Blog for more in depth stories on pragmatic code for happy users!