In the first part we’ve covered what I believe are the required engineering skills to do a great job in software development. In this second part, we will talk about what platform specific knowledge is needed to be complete iOS Software engineer.
Objective-C / Swift
We will start off with the languages. With the announcement of Swift, now there are two programming languages that every iOS developer needs to master. Yes, you only need one language to develop iOS apps, but that’s not enough – I strongly believe that you should know both of them. If you are, let’s say just starting out as iOS engineer, you might think “Oh, I will just learn Swift, since it’s newer and people say it’s better, it should be enough”. But, if you are working in a company, you might implement new features in an existing Objective-C application, or you might use third party Objective-C code and you need to modify something, or you look for something on the web (tutorial) and there’s only Objective-C example. How would you do all these things if you don’t know Objective-C?
The reverse is also true – let’s say you are Objective-C developer for many years and don’t know (or don’t want to learn) Swift. This leaves the impression that you are not that flexible about new languages and tools and don’t want to learn new stuff. And constant learning is crucial for the job. Swift is the language for the future, ignore it at your own peril.
Apart from just knowing the syntax, you should be aware of the language specific differences and features. So for example, you have to know about Objective-C’s runtime or the Swift specifics like value types, protocol extensions, optionals, generics.
Deep knowledge of the iOS SDK
I thought I knew a lot about iOS development. Then someone pointed out to me Mike Ash’s blog and I’ve realized how much more there’s to learn and master. I recommend everyone to check it out and learn in depth how the iOS SDK works. The excellent and deep explanations in this blog will prove to be very helpful, especially if you want to implement something different on lower level that’s not currently available in the iOS SDK.
In any case, you should know a lot about Foundation and its most used classes, then about UIKit (views, layout, animations), Delegation, Blocks, Grand Central Dispatch, Networking etc. Although now the iOS SDK has automatic reference counting, you have to know about memory management on iOS. ARC is not Garbage collection and it doesn’t detect and handle memory leaks. That’s why you need to understand the different types of references (weak, strong, unowned) that are assigned to variables, because this information is used by ARC to determine the places where the automatic releases are inserted.
Different ways of building UI
Most of the time in our work, we are building complex user interfaces. It’s really important to know which approach is suitable for which UI. If you are just writing imperative UI code all the time to set autolayout constraints and configure views, that’s pretty bad sign. First, you are wasting a lot of time to write the code, then you will waste a lot of time to maintain it. If you miss one constraint, you will not have any warning that something is wrong. Also, you will make it really hard for others to understand your code.
A better option is to use the interface builder. With this option, you will get rid of a lot of code, set the autolayout constraints visually and configure most of the view in the builder. Of the two interface builder options – xibs or storyboards you should choose the one that’s more applicable to your use case. If you want to develop something quickly, if you don’t care about introducing strong coupling between your screens and you don’t expect much changes in the app flow in the future, probably storyboards are the better option. In any other case, using xibs gives you more flexibility if you do it right. One good pattern is to abstract away the pushing of screens to a separate class (e.g. navigation center), which will handle which screen should be pushed next. This will enable better decoupling between the screens and make your life easier in the future.
Interface builder is good for most cases, but it has it’s own pitfalls. The most obvious one is that it’s a complex xml file behind the scenes, with a lot of auto generated Apple stuff. It might be a nightmare to merge changes that two or more developers did on the same file (whether that be a storyboard or xib) at the same time. This makes it a bit impractical for larger teams. Another problem is performance, if you have a lot of complex view hierarchies with many subviews, that might slow down your app. These problems might not appear in most of the apps, but if you have an app as big as Facebook or Instagram, they surely will. That’s why Facebook is pioneering a more reactive and declarative approach to building the UI. You just tell what you want to be drawn via abstractions called Components to the drawing infrastructure and you have as a result a configured view. With this approach, you have all your drawing in one place, abstracted away from other parts of your code. For more details, check this blog post and watch this presentation. Another interesting and very helpful detail with this approach is that you have one directional data flow from models to components to views, while enforcing immutability. That also allows you to move some drawing code to a background thread.
Moving layout code to other threads can significantly improve the user experience for complex apps. If you still don’t want to embrace the reactive approach (which has it’s challenges as well, especially with performing animations), you can also check rendering libraries like AsyncDisplayKit. This one is very similar to UIKit and it also support drawing in background as well as many other optimizations. It’s used in Pinterest and Facebook Paper apps.
There are many options to develop the UI of your apps and you should be aware of the pros and cons of every approach.
All the user interactions go on the main thread, which means most of the work your app does has to be on other threads. Otherwise, the app will block and your users would be unhappy. That’s why all mobile developers should have deep understanding of concurrency – threads, Grand Central Dispatch, race conditions, deadlocks, starvation. There are excellent posts on the topic in one of the best blogs for iOS development, objc.io. There you will find most of the things you need to know, combined with Mike Ash’s posts (mentioned above) for concurrency.
Ways to do networking
Mobile apps would be boring and not that social if they didn’t communicate with servers to get the latest data, therefore doing proper networking is a must have skill. With networking, you have to find the right balance between not reinventing the wheel and integrating really large framework where you might not need many of its features. That’s why I would recommend that you should only use the big libraries like AFNetworking only if you need many of its features. Otherwise, you can either use smaller ones or develop one by yourself and re-use it / extend it in future projects. If you do that, going open source is always a good option to brush away some bugs you might have.
Different architectures for iOS apps
Choosing the appropriate architecture can be make or break for your mobile apps (and any other software projects). Deep understanding of the software requirements, experience and research / analysis of the available options is needed in order to make the correct decision.
The standard and most obvious iOS app architecture is Model – View – Controller (MVC). It’s supported by default by the iOS SDK and if done right, can be a good option for small to medium projects. One thing you have to be careful of is to avoid putting too much stuff in the view controllers and use utility / service classes as much as possible. Otherwise, MVC will become the Massive View Controller, your controllers will know/do too much things and everything will be harder to manage and maintain. Testing is also an issue, since the view controllers are deeply connected with their views.
There are several approaches to address the pitfalls of MVC. One of them is Model-View-ViewModel, where you extract the presentation logic to a new class ViewModel, which is reusable and testable. With this architecture, it’s best to use reactive extensions like RXSwift or RXCocoa, to propagate the model changes back to the view.
Other approach is VIPER – View, Interactor, Presenter, Entity and Router. This one is suitable for bigger projects where decoupling between the different components is needed. Haven’t used it personally, but it looks promising.
Although most of the time apps consume data from the web and store it in memory, sometimes there’s a need this data to be saved locally in the phone and be available between app launches. I’ve seen a lot of posts and iOS interview questions where the knowledge of CoreData specifics is considered a must for every iOS developer. I don’t agree with this, since CoreData is just one of the many options out there. If it hasn’t been adequate for my apps, why do I need to know its specifics? I’m not saying CoreData is bad, I’ve used it in a project – what I’m saying is that knowledge of the different persistence options and the reason why you’ve picked particular one is important – not CoreData itself. If you’ve picked CoreData and you have valid arguments why you did that, that’s perfect. The same holds if you’ve developed your own wrappers over SQLite, or you are using the iOS File System with cached json / xml files or you are persisting only small data with user defaults. Performance is also a big factor here in the selection of the right option.
Keeping an eye on new APIs
In Apple’s ecosystem, things change really fast and you always have to adapt to those changes. You might have felt that when you’ve migrated your apps from Swift 2 to Swift 3. We all know that Apple doesn’t care much about older iOS versions and pushes its users to always update to the latest iOS versions. This means you always have to keep track on what’s new and what’s changed and test your apps with every beta release.
Apart from the stability of your apps, you should keep an eye on all the new APIs that Apple announces and think how you might want to incorporate those in your apps, since users might expect that. For example, SiriKit was introduced in the latest WWDC – if your app expects user input which requires a lot of typing, SiriKit might speed up that process significantly and make your users happier.
That was all for the second part of the series. These are the core things I would expect great iOS developers to posses. The series were concentrated on technical things mostly, but soft skills are as equally important. Without having the right enthusiasm, passion to do amazing work and constant learning, you can’t be great in the industry. If you want to do something big, you also have to be a great team player, because no one can do anything significant by themselves.