In this article you'll find iOS interview questions and answers for senior developers. This article continues the work I’ve done before writing The iOS Interview Guide and I will update it every year. In this 2020 edition, I added several new things from my experience and companies where I worked to help you be ready for iOS interview questions now. I updated the article to fully focus on Swift, since Objective-C has become rarer, and added questions on Fundamentals of iOS, Unit Testing and Architecture for Scale.
NOTE: if you have an inteview question you want me to answer you can submit it here.
When you’re preparing for your technical iOS interview, it’s important to understand what you could be asked about topics and what is expected from a seasoned iOS developer. These questions and topics (in one form or another) are used by many companies to gauge the level of experience in an iOS candidate. They cover various aspects of iOS development and aim to touch upon a broad understanding of the platform. Senior developers are expected to be able to ship full iOS products from start to finish, after all. But in large companies with big iOS development teams (think 25+ people) specialization and focus on a deep knowledge of a specific problem such as networking also occurs though. This is by no means an exhaustive list, but it can help you prepare for your upcoming technical iOS interview.
In the sections below I’ll go over each question, the reasoning behind it, the expected answer, and the answers that could raise a red flag for your interviewer. Where applicable, questions have further reading section where you’d find links and references to more material related to them.
1 What are the main features and advantages or disadvantages of Swift?
This might sound like a beginner question, but it’s not. Sometimes it might be asked to gauge experience you have with other languages and your broader understanding of what the language you use gives you and its advantages, disadvantages, and limitations.
TLDR: main Swift features - static typing, protocols, reference types, value types, optionals, generics.
Swift is a strongly typed language, which might be its biggest feature, advantage and disadvantage at the same time. Static typing allows protocols, generics, and optionals to exist and aids you in development. Static typing gives you a lot of compile-time warnings and compilation errors, but provides greater runtime safety and determinism (optionals, var/let, generic or concrete types, etc.). This is one of the biggest advantages that the language provides. It is the most helpful to have strict type safety in the following scenarios:
- when you’re building a client application and you need more strict explicitness rather than dynamism and flexibility
- when you’re working in an environment where you want to restrict less experienced developers (beginners and juniors) from having too much power and shooting themselves in the foot
- when you need to refactor your code and the compiler serves as an aid to writing your code properly and correctly
All of those happen to be the majority of customer facing applications iOS developers build.
At the same time static typing could be too restrictive when you’re building something that requires more flexibility such as building a library or a framework. Objective-C could be a better choice in that regard as it allows better meta-programming capabilities than Swift. (Although arguably at this point Objective-C becoming obsolete and all the development for Apple platforms should be done in Swift)
You will be fine as long as you can articulate what each feature offers, i.e. what do protocols and generics actually allow you to do in code? But again, those are arguably a minor language features compared to the strict type system.
Further reading for this question:
2 What is an iOS application and where does your code fit into it?
This is a big-picture question asked, in one form or another, to gauge your understanding of what an iOS application is, and where the code you write fits in it and in the iOS system overall.
We might think the apps we build are something special because they cover a unique use case. But your typical iOS application is just a giant, glorified run loop. It waits for user input and gets interrupted by external signals such as phone calls, push notifications, home gestures/button presses, and other app life cycle events. The only difference is that instead of being just a simple main loop function that gets launched every time the user taps on your app icon, it has a higher level of abstraction, UIApplication, AppDelegate, and SceneDelegate that developers work with.
The rest of the code you write to implement the business logic of your app is placed somewhere in the “trigger points” delegated by that main loop to our app via
SceneDelegate. Before iOS 13
AppDelegate was responsible for receiving all external events for your application and spinning up the UI; but starting with iOS 13 all UI-related logic was moved to SceneDelegate.
That’s it. Simple. The code you write for your app can be as simple as a method/function call, or as complex as VIPER architecture. It’s your choice.
Typically developers think of iOS apps as the MVC code they write and the complex intricate details of the implementation, which is true. But if you take a step back and look at the big picture, you can see what iOS apps really are - a run loop.
Further reading for this question:
3 How is memory management handled in iOS?
Memory management is very important in any application, especially in iOS apps that have memory and other hardware and system constraints. This question refers to ARC, MRC, reference types, and value types.
Swift uses Automatic Reference Counting (ARC). This is conceptually the same thing in Swift as it is in Objective-C. ARC keeps track of strong references to instances of classes and increases or decreases their reference count accordingly when you assign or unassign instances of classes (reference types) to constants, properties, and variables. It deallocates memory used by objects whose reference count dropped to zero. ARC does not increase or decrease the reference count of value types because, when assigned, these are copied. By default, if you don’t specify otherwise, all the references will be strong references.
This is a must know for every iOS developer! Memory leaks and app crashes are all too common due to poorly managed memory in iOS apps.
Further reading for this question:
4 What is MVC?
Oh, good old MVC. This is a fundamental design pattern Apple keeps pushing onto iOS developers. Most likely every single interviewer will ask about this regardless whether you’re applying for a senior or junior position. Your answer as a senior would be different though.
MVC stands for Model View Controller. It is a software design pattern Apple chose as the main approach to iOS application development. Models represent application data; views draw things on the screen; controllers manage data flow between model and view. Model and view never communicate with each other directly and rely on a controller to coordinate the communication. This design pattern is morphed by Apple into something else from its
original SmallTalk implementation.
A typical representation of each Apple MVC layer in an iOS application would be:
- UIView subclasses (Cocoa Touch or custom) are views
- UIViewControllers and their subclasses are controllers
- any data objects, NSManagedObject subclasses and similar are models
MVC is a great general purpose design pattern, but as a senior developer you should know that it is just a design pattern for the view layer and using it alone limits your architecture and often leads to the notorious “Massive View Controller” problem.
Massive View Controller is the state of a codebase where a lot of logic and responsibility was shoved into View Controllers that doesn’t belong there. That practice makes your code rigid, bloated, and hard to change. There are other design patterns that can help you remedy this, such as MVVM, MVP, and Coordinator. And there are archictures such as VIPER and RIBs that were made specifically for the purpose of scaling iOS code and avoiding Massive View Controller problem.
Even though Apple keeps telling us that MVC is everything, know better and stick to SOLID principles.
You absolutely have to know what MVC is since it’s basic to any iOS development. Though, explore alternatives and additions such as MVVM, MVP, VIPER, and RIBs.
Further reading for this question:
5 What do you know about singletons? Where would you use one and where would you not?
Singleton is a common design pattern used in many OOP languages, and Cocoa considers it one of the “Cocoa Core Competencies”. This question comes up on interviews to either gauge your experience with singletons, or find out if you have a background in something other than just iOS.
Singleton is a class that returns only one and the same instance no matter how many times you request it.
Singletons are sometimes considered to be an anti-pattern. There are multiple disadvantages to using singletons. The main ones are global state, object life-cycle, and dependency injection. When you have only one instance of something, it’s very tempting to reference and use it everywhere directly instead of injecting it into your objects. That leads to unnecessary coupling of concrete implementation in your code instead of working with an interface abstraction.
Another malicious side effect of “convenient” singletons is the global state. Often singletons enable global state sharing and play the role of a “public bag” that every object uses to store state. That leads to unpredictable results and bugs or crashes when this uncontrolled state gets overridden or removed by someone.
Even though in some languages and platforms singletons are considered to be good, they are in fact an anti-pattern that should be avoided at all costs.
6 What’s different between delegate and KVO?
With this question, your interviewer is assessing your knowledge of different messaging patterns used in iOS.
Both are ways to have relationships between objects. Delegation is a one-to-one relationship where one object implements a delegate protocol; another sends messages to it, using methods defined by the protocol. KVO is a many-to-many relationship where one object broadcasts a message, and one or more other objects listen to it and react. KVO does not rely on protocols. KVO is the first step and the fundamental block of reactive programming (RxSwift, ReactiveCocoa, etc.)
A seasoned developer should know differences between the two, and where to use one over another.
7 What design patterns are commonly used in iOS apps?
This question is common on interviews for positions of all levels, except maybe junior positions. Working with the iOS platform, developers should be familiar with techniques, architecture, and design patterns commonly used on iOS.
Typical commonly used patterns when building iOS applications are those that Apple advocates in their Cocoa, Cocoa Touch, Objective-C, and Swift documentation. These are the patterns that every iOS developer learns. Apple refers to them as “core competencies” design patterns. They include MVC, Singleton, Delegate, and Observer.
When an interviewer asks this question (in one form or another), he is looking for something besides MVC. Because MVC is the go-to design pattern, the expectation is that every iOS developer knows it. What they want to hear from you, though, is what else we commonly use out of the box.
8 What are design patterns besides common Cocoa patterns that you know?
This is an advanced question that an interviewer will ask when you interview for a senior or architect position. The expectation is that you know more practical design patterns used in iOS apps beyond the basic ones covered in the earlier question. Be ready to recall a bunch of Gang of Four patterns and other similar patterns.
Design patterns are a huge topic on their own (they are covered better in my book), so here I’ll only summarize those I see commonly in iOS code bases.
Besides commonly used MVC, Singleton, Delegate, and Observer patterns, there are many others that are perfectly applicable in iOS applications: Factory Method, Adapter,Decorator, Command, and Template.
Factory Method is used to replace class constructors, to abstract and hide objects initialization so that the type can be determined at runtime, and to hide and contain
switch/if statements that determine the type of object to be instantiated.
Adapter is a design pattern that helps you, as the name suggests, adapt the interface of one object to the interface of another. This pattern is often used when you try to adapt third-party code that you can’t change to your code, or when you need to use something that has an inconvenient or incompatible API.
Decorator is a wrapper around another class that enhances its capabilities. It wraps around something that you want to decorate, implements its interface, and delegates messages sent to it to the underlying object or enhances them or provides its own implementation.
Command is a design pattern where you’d implement an object that represents an operation that you would like to execute. That operation can have its own state and logic to perform the task it does. The main advantages of this design pattern are that you can hide internal implementation of the operation from the users, you can add undo/redo capabilities to it, and you can execute operations at a later point in time (or not at all) instead of right away where the operation was created.
Template is a design pattern where the main concept is to have a base class that outlines the algorithm of what needs to be done. The base class has several abstract methods that are required to be implemented by its concrete subclasses. These methods are called hook methods. Users of the Template Method classes only interact using the base class that implements the algorithm steps; concrete implementations of those steps are supplied by subclasses.
Sticking only to MVC, Singleton, Delegate, and Observer patterns is fine when you’re just starting with the iOS platform, but for advanced things you need to reach deeper into more abstract and high-level stuff like Gang of Four OOP Design Patterns. They are very useful and make your codebase more flexible and maintainable.
9 Explain and show examples of SOLID principles?
SOLID principles are relatively old but incredibly useful concepts to apply to any OOP codebase in any language. Watch a few of Uncle Bob’s talks on the topic to fully appreciate the history behind them.
SOLID stands for Single Responsibility Principle, Open/Closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle. These principles feed into and support each other and are one of the best general design approaches you could take for your code. Let’s go through each of them.
The Single Responsibility Principle (SRP) is the most important principle of the group. It states that every module should have only one responsibility and reason to change. SRP starts with small concrete and specific cases such as a class and/or an object having only one purpose and being used only for only one thing.
The Open/Closed Principle (OCP) states that your modules should be open for extension but closed for modification. It’s one of those things that sounds easy enough but is kind of hard to wrap your head around when you start to think about what it means. Effectively it means that when writing your code you should be able to extend the behavior of your objects through inheritance, polymorphism, and composition by implementing them using interfaces, abstractions, and dependency injection.
The Liskov Substitution Principle (LSP) states that objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. What that means is that when you inherit from a class or an abstract class or implement an interface (protocol), your objects should be replaceable and injectable wherever that interface or class that you subclassed from was used. This principle is often referred to as design by contract or, as of late in the Swift community, referred to as protocol-oriented programming. The main message of this principle is that you should not violate the contract that your interfaces you subclass from promise to fulfill, and that by subclassing, those subclasses could be used anywhere that the superclass was previously used.
The Interface Segregation Principle (ISP) says many client-specific interfaces are better than one general-purpose interface. It also states that no client should be forced to depend on and implemented methods it does not use. What that means is that when you create interfaces (protocols) that your classes implement, you should strive for and depend on abstraction over specificity, but not until it becomes a waste where you have to implement a bunch of methods your new class doesn’t even use.
The Dependency Inversion Principle (DIP) states, “depend on abstractions, not concretions.” The best example that showcases this principle is the Dependency Injection (DI) technique. With the Dependency Injection technique, when you create an object, you supply and inject all of its dependencies upon its initialization or configuration rather than let the object create or fetch/find its dependencies for itself.
Further reading for this question:
10 What options do you have for implementing storage and persistence on iOS?
Interviewers ask this question to grasp your understanding of what tools and ways you have available to store and persist data on iOS.
Generally there are the following ways to store data in order from simple to complex:
- In-memory arrays, dictionaries, sets, and other data structures
- File/disk storage
- Core Data, Realm
In-memory arrays, dictionaries, sets, and other data structures are perfectly fine for storing data intermediately or if it doesn’t have to be persisted.
NSUserDefaults/Keychain are simple key-value stores. One is insecure and the other is secure, respectively.
File/disk storage is a way of writing data (serialized or not) to/from a disk using NSFileManager.
Core Data and Realm are frameworks that simplify work with databases.
SQLite is a relational database and is good when you need to implement complex querying mechanics and Core Data or Realm won’t cut it.
You should know different ways you could store data on iOS and their advantages or disadvantages. Don’t limit yourself to only one solution that you’re used to (like Core Data, for example). Know when one is preferable over the other.
Further reading for this question:
11 What options are available for networking and HTTP on iOS?
Every application these days uses networking to get data from APIs and other external resources. Many apps are useless when not connected to the internet. Every iOS developer should know what’s available to them to build the service/networking layer of their application.
In iOS there are several options to implement HTTP networking. You can go with good old NSURLSession, but unless you abstract it out well enough, it can be daunting to work with. Another option would be to use a wrapper library around it. The most popular solution on iOS is Alamofire.
In general, if you have a small team you likely want to rely on open sourced solutions such as Alamofire that abstract a lot of boilerplate code out for you; but if you’re in a big team and can spare resources you’d want have more control over how data is passed to/from your server and implement it yourself using NSURLSession.
Senior developers should keep in mind that building the networking layer in iOS applications means not only dealing with HTTP requests but implementing the whole set of tasks your code does related to that: HTTP networking, data serialization, and data mapping.
These days, NSURLSession and Codable are the two main technologies used for networking on iOS but also knowing about open source solutions such as Alamofire is beneficial.
12 How and when to serialize and map data on iOS?
Data serialization is a common task when building iOS applications. Interviewers ask this question to see if you recognize where it’s suitable and know of the tasks needed when working with data, whether it’s networking or storage data.
There are two most common scenarios where you’d need to serialize and map data in iOS applications: receiving or sending data in the networking layer (such as JSON or XML or something else), and persisting or retrieving models in the storage layer (NSData, NSManagedObject).
Every time you receive JSON or XML or any other response type of response from a backend API, you most likely get it in a JSON or binary or other “inconvenient” format. The first thing you need to do to work with the data you’ve received is to serialize it in something your app understands. At the most simplest and basic level that would be a dictionary or an array of objects containing other dictionaries, arrays, and primitives from that response. NSJSONSerialization takes care of that. The next step is to map that data into domain models of your application. Those would be the model objects or structs for the rest of your application to use. You can either do it manually or use
Codable protocol provided by Apple or use a library such as Mantle or SwiftyJSON. The flow of data and serialization/mapping is:
binary data ->
your domain model objects.
Similarly, in the storage layer, you will need to serialize and map your data to and from your custom domain model objects to the format your storage understands. The “mapping” chain for reading data:
raw data format ->
custom domain models; and for writing:
custom domain models ->
raw data format ->
db. You’d use the NSManagedObject or NSCoding or Codable protocol here to achieve that.
The main red flag here is not being aware that these data manipulations need to happen when working with the networking and storage layers of your iOS applications. Things do not happen “automagically”, nor is working with raw NSDictionaries appropriate and maintainable.
13 What are the options for laying out UI on iOS?
Knowing your options for laying out things on the screen is crucial when you need to solve different UI challenges on iOS. This question helps gauge your knowledge about how you putplace and align views on the screen. When answering this question, you should at least mention CGRect, Fframes and, AutoLayout, and SwiftUI, but it would be great to mention other options such as Texture (ASDK), ComponentKit and other Flexbox and React implementations on iOS.
Go-to options for laying out views on the screen are good old CGRect Frames and AutoLayout. Frames, along with auto-resizing masks, were used in the past before iOS 6 and are not a preferred option today. Frames are too error-prone and difficult to use because it’s hard to calculate precise coordinates and view sizes for various devices.
Since iOS 6 we have AutoLayout, which is the go-to solution these days and which Apple prefers. AutoLayout is a technology that helps you define relationships between views, called constraints, in a declarative way, letting the framework calculate precise frames and positions of UI elements instead.
With iOS 13, Apple introduced a new approach for laying out views - SwiftUI, which is a declarative approach that supports FRP (functional-reactive programming) data bindings with Combine. FRP and declarative UI are not new concepts, but SwiftUI and Combine are new frameworks from Apple that support it. The declarative nature of SwiftUI allows you to declare your UI elements very concisely and then later through data bindings declare what parts of the UI, such as text labels for example, to update upon what data model changes. In effect, it allows you to do what was already possible with RxSwift before, but now with Apple frameworks.
There are other options for laying out views, such as ASDK (Texture), ComponentKit, and LayoutKit, and some of them are more or less inspired by React and others solve layout Asynchronicity differently. These alternatives are good in certain scenarios when, for example, you need to build highly dynamic and fast table views and collection views. AutoLayout is not always perfect for that and knowing there are other options is always good.
NOTE: we’ll see how SwiftUI proves itself solving complex UI problems and complex async UI layout problems in the future, it’s a very new technology as of the time of this writing.
Not mentioning at least AutoLayout and the fact that frames are hard to get right will be a red flag for your interviewer. These days no sane person would do CGRect frame calculations unless it's necessary (for example, when you do crazy drawings).
It won’t be a red flag yet, but mention SwiftUI and that this likely will be what Apple will push on us in coming years.
14 How to optimize scrolling performance of dynamically sized table or collection views?
One of the important questions on interviews along with UITableView questions is about scrolling performance.
Scrolling performance is a big issue with UITableViews and quite often can be very hard to get right. The main difficulty is cell height calculation. When the user scrolls, every next cell needs to calculate its content and then height before it can be displayed. If you do manual Frame view layouts then it is more performant but the challenge is to get the height and size calculations just right. If you use AutoLayout then the challenge is to set all the constraints right. But even AutoLayout itself could take some time to compute cell heights, and your scrolling performance will suffer.
Potential solutions for scrolling performance issues could be:
- calculate cell height yourself
- keep a prototype cell you fill with content and use it to calculate cell height
Alternatively, you could take a completely radical approach, which is to use different technology like ASDK (Texture). ASDK (Texture) is made specifically for list views with dynamic content size and is optimized to calculate cell heights in a background thread, which makes it super performant.
Further reading for this question:
15 How would you execute asynchronous tasks on iOS?
Multithreading is a vital part of any client-side, user-facing application these days. This question could be asked in the context of networking or as a standalone question about GCD or async development.
These days on iOS your go-to solutions for async tasks are NSOperations and GCD blocks. Grand Central Dispatch is a technology that was made to work with multiple background queues that in turn figure out which background thread handles the work. The main thing is that this is abstracted out from you so that you don’t have to worry about it. NSOperation is an OOP abstraction on top of GCD that allows you to do more sophisticated async operations, but everything you could achieve with NSOperations you could do with GCD. Many Cocoa frameworks use GCD and/or NSOperations under the hood (NSURLSession for example).
There are alternative ways of handling async work using third-party libraries’ help. The most notable are Promises (PromiseKit), RxSwift, and ReactiveCocoa. RxSwift and ReactiveCocoa are especially good at modeling the asynchronous nature of time and work that needs to be done in the background and coordinated among threads.
The basics that every iOS developer should know about async work are GCD and NSOperations. RxSwift and Promises are advanced concepts, but senior developers should know them.
16 How do you manage dependencies?
Dependency management is an important task in every iOS project. This question gauges your understanding of the problem and its solution.
A few years back, we didn’t have any dependency managers on iOS and had to copy-paste and drag-and-drop third-party code into our projects or to use Git sub-modules. Those approaches proved to be unmanageable as our codebase and dependencies grew.
These days we have other dependency managers to choose from: CocoaPods, Carthage, and Swift Package Manager.
So far the most dominant and robust one is CocoaPods. I was built in the spirit of the Ruby Bundler gem and is a Ruby gem itself. The way it works is you install the gem, create
Podfile in the root directory of your project, declare the pods (libraries) you want to use, and run
pod install. That’s it.
With Carthage, you create a dependencies declaration file called
Cartfile but unlike Cocoapods you’d need to do Xcode project setup to make it work.
Swift Package Manager is the future of dependency management for any Swift project but it only supports libraries and frameworks and cannot be used to generate iOS targets, although iOS targets can depend on modules built by SPM.
Every iOS developer should understand why copy-pasting third-party libraries into your codebase leads to a maintenance nightmare when several libraries could depend on two different versions of another library, causing mismatches and compile and runtime issues.
17 How do you debug and profile code on iOS?
No one writes perfect code, and developers need to debug their code and profile apps for performance and memory leaks.
You can do more advanced debugging and profiling using
Instruments is a profiling tool that helps you profile your app and find memory leaks and performance issues at runtime.
Further reading for this question:
18 Do you have TDD experience? How do you unit and UI test on iOS?
Even though, historically, the iOS community wasn’t big on TDD, it is now becoming more popular thanks to improvements in tooling and influence from other communities, such as Ruby, that embraced TDD a long time ago.
TDD is a technique and a discipline where you write failing tests first before you write production code that makes them pass. The tests drive implementation and design of your production code, helping you write only the code necessary to pass the tests implementation, no more, no less. The discipline could be daunting at first and you don’t see payoff of that approach immediately, but if you stick to it, it helps you move faster in the long run. It is especially effective at helping you with refactoring and code changes because at any given time you have the safety net of your tests to tell you if something broke or if everything is still working fine as you change things.
Recently Apple made improvements to XCTest frameworks to make testing easier for us. They also made a lot of improvements with UI testing in Xcode (XCUITest), so now we have a nice programmatic interface to interact with our apps and query things we see on the screen. Alternatively you could go with frameworks like KIF, iOSSnapshotTestCase, EarlGrey.
In regards to unit testing, there are several options as well, but the two most popular ones are XCTest and Quick and Nimble.
XCTest is a xUnit like testing framework built by Apple. This is what they recommend to use, and it has the best integration with Xcode.
Quick is a RSpec-like BDD framework that helps you describe your specs/tests in terms of behavior rather than “tests.” Fans of RSpec like it a lot.
Nimble is a matcher library that can be used with XCTest or Quick to assert expectations in your tests/specs.
More and more teams and companies embrace TDD, and it has become a vital part of the iOS development process. If you don’t want to be left behind, get on board with it and learn how to test-drive your code.
19 What different between mocks, stubs, and fakes?
As testing becomes a more prominent and important practice in the iOS world, it’s important to know what you’re doing as you write your tests. Your test code is as important as your application code. This question gauges your understanding of testing terminology for objects used to aid in unit-testing.
There are various ways different people call and categorize test objects but most commonly test objects can be categorized in the following way: fakes, stubs, and mocks.
Fakes is the general umbrella term for any kind of mock, fake, stub, double, etc. On their own, they typically have no implementation and only fulfill the interface API requirements of the types they are substituting.
Stubs are fakes that do some meaningful work that’s necessary for the objects involved in a test to operate, but not used for anything more than that. They can’t be used in place of real production objects but can return stubbed values. They can’t be asserted on.
Mocks are fakes that can be asserted on. Mocks are used in place of other objects just like a fake, but they themselves record some data such as the number of method calls or variables passed for your test to assert on later.
Many developers make a mistake of calling any test object a mock, but there is a specific distinct nomenclature for test objects that indicates the purpose for each one. As a senior developer you’re not merely writing tests, you also should know how to maintain them as well as your application codebase.
Further reading for this question:
20 Do you code review and/or pair program?
Even though there are a lot of applications out there that were built by solo developers, the complexity of what apps do keeps increasing, demanding that a team of developers work on it. Working in a team poses different challenges in terms of code maintenance, collaboration, and knowledge sharing.
Pair programming is a practice where two developers work on the same task together on the same machine (hopefully not sharing the same screen and keyboard and having two sets of their own). The goal is to facilitate collaboration, discussion, code review, and QA right where the code gets produced. This process makes knowledge transfer and architectural discussions a common day-to-day thing, preventing people from siloing and becoming “an expert” in a certain part of the code (what happens when that person leaves or gets sick?). It also improves code quality because two sets of eyes are looking at the code as it’s written. This process happens for two developers at the same time and is sometimes called synchronous.
Pair programming is not for everyone and could be an exhausting process if people’s personalities do not match. But nevertheless it is one of the most efficient collaboration techniques in software development.
Code review is a similar process of collaboration and knowledge transfer, but unlike pair programming, it doesn’t happen at the same time, and therefore it is asynchronous. With code review, after a developer writes a piece of code or a feature, someone else on the team has a look at it. The reviewer checks if the code makes sense and suggests changes and refactorings to be done to improve it. That opens up an online or offline discussion about the code, which is great. That transfers knowledge about that piece of code to other teammates and helps catch bugs and design smells early on.
Code reviews are a less-involved type of collaboration that achieves much of the same results as pair programming does. It also is an exercise in empathy where you’re giving feedback to others on their work.
Further reading for this question:
21 What is FRP (Functional Reactive Programming) and its place in iOS platform?
Functional Reactive Programming (FRP) is a declarative programming paradigm that combines functional programming and reactive (async dataflow programming) paradigms. It is a declarative style of programming where you declare what your code does rather than state how it does it. The reactive component of FRP allows us to introduce and describe the concept of time, which is hard to work with in pure functional programming. FRP helps us deal with user input and the asynchronous nature of iOS applications in general; user input happens at some point in time, networking will finish some time in the future, etc.
FP and FRP rely on higher-order functions such as map, reduce, and filter that take functions as arguments and return other functions, which makes them highly composable.
Swift doesn’t have native support for FRP, but there are two excellent libraries that implement functional reactive programming concepts and make them easily available to us: ReactiveCocoa and RxSwift.
In iOS 13, Apple also announced a new FRP framework built into iOS called Combine. Combine is effectively an FRP framework implementation similar to RxSwift. The two advantages it has: it’s integrated with SwiftUI allowing it to bind UI elements to data changes, and it’s built-in and supported by Apple. Disadvanges are: it’s less mature than RxSwift and Apple will be slow to make changes and additions to it.
FRP is becoming more commonplace in iOS apps and will be used more with Apple's official support of this programming paradigm with Combine. iOS developers should start embracing it.
22 What iOS architectures do you know that scale?
This question likely will be asked interviewing for a big company with a large iOS development team. iOS apps are becoming increasingly complex and MVC design pattern doesn’t hold up well as a large scale application architecture. This is a very advanced question for Seniors, Leads, Architects, etc.
MVC, MVVM, MVP, and similar design patterns are great and each is an improvement on the other, but they still do not scale well for teams larger than 10 or 20 people. If you’re beyond that team size, you need to use a more generic and scalable architectural approach. There is such a conceptual approach, called Clean Architecture.
Clean Architecture is a conceptual application architecture for scale and can be simply described as “an onion layered architecture”. The main idea is to keep dependencies pointing inward towards your domain logic and domain models and keeping everything else pluggable and optional (the way you store data, render ui, receive or send networking requests, etc.). This architecture scales particularly well for large teams of 100+ developers.
There are two concrete implementations of Clean Architecture on iOS: VIPER and RIBs.
VIPER stands for View, Interactor, Presenter, Entity, and Router. Those are the building blocks of that architecture. In this architecture, everything starts with a router and ends with a view. Each VIPER stack (meaning a set of a View, Interactor, Presenter, Entity, and Router) is one screen or one logical UI part of your application. To navigate and use a VIPER stack, you'd instantiate its router and then ask it to create its view controller. The router creates a view controller, a corresponding presenter that formats data for the view and receives user input for the view, an interactor that holds business logic and communicates with presenter, and entities necessary for interactor to work. Then the VC owns presenter, presenter owns interactor, and interactor owns entities and the router. The resulting view controller is used in your view hierarchy and inserted, pushed, or presented as necessary. This architecture allows for strong encapsulation of logic and scalability for team size since every part of your app is now a VIPER stack.
RIBs stands for Router, Interactor, Builder. RIBs is another implementation of Clean Architecture that was an improvement on VIPER. In RIBs architecture, the main building block is a RIB, a set of one router, one interactor, and one builder with optional view and presenter. RIBs without a view are called headless RIBs. Just like in VIPER architecture, you route from one RIB to another using router, and that structures the entire runtime of your app in as a tree structure with parent and children RIBs. Since the view is optional, unlike with VIPER, your application tree structure might or might not mimic your view hierarchy.
Builder is responsible for fetching or creating dependencies for the interactor, router, and the view/presenter assembling and initializing them.
Router is responsible for navigating to specific children RIBs.
Interactor is responsible for all the business logic and initiating routing using router.
Presenter and the view are typically combined in a view controller where presenter is responsible for massaging and formatting data for display in the view.
View is responsible for display data on the screen and collecting user input.
The questions covered in this post touch upon a broad spectrum of topics iOS developers should know. This is by no means a comprehensive list. These questions are based on research I’ve done for the book, The iOS Interview Guide, which I published. The book approaches interview prep as a holistic overview of iOS topics and concerns every iOS application has. It breaks down questions into the following groups: UI-related questions (UIView, AutoLayout, etc.), storage questions (persistence, user defaults, core data, etc.), networking (http, NSURLSession, Alamofire, etc.), and design patterns and architecture questions (MVC, MVVM, SOLID, etc.). It has been a great help for more than a thousand of developers who used it help them with interview prep.
P.S. if you have an inteview question you want me to answer you can submit it here.