The iOS Interview Guide by Alex Bush

The iOS Interview Guide

6.2/108 min read

1/21/20

  • An iOS application is a giant run loop. It waits for user input and gets interrupted by external signals such as phone calls, push notifications, home button press, and other app life cycle events

  • Callback methods to UIAppDelegate: application:willFinishLaunchingWithOptions:, application:didFinishLaunchingWithOptions:, applicationDidBecomeActive:, applicationDidEnterBackground:, applicationWillResignActive:, applicationWillEnterForeground:

  • Your code can be grouped into the following layers of responsibility: storage layer, service layer, business logic layer, and UI layer

  • The key to a happy and healthy iOS codebase is a skinny controller

  • The business logic layer helps us keep services, storages, and other layers decoupled from each other and tells them what to do to achieve results. This layer makes your application useful

  • SOLID principles: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion

  • Structs and classes have properties, methods, subscripts, initializers, can be extended, and conform to protocols

  • Classes are reference types

  • Structs are value types

  • Properties in Objective-C are used to store data in instances of classes

  • Protocols are declarations of what a type that adopts them should implement

  • Categories allow you to add additional methods to a class or type without subclassing

  • Categories cannot add new properties

  • Categories are globally applied to all instances of the type

  • Blocks are an executable piece of code that will be used at a later time

  • Blocks retain a reference to everything put in them unless otherwise specified with __block or __weak

  • Singleton is a class that returns only one-and-the-same instance no matter how many times you request it

  • The Delegate pattern is a variation of the Observer pattern where only one object can observe events coming from another objecct

  • Delegates are a one-to-one relationship

  • KVO (Key-Value Observation) allows you to observe changes on properties in iOS

  • Many-to-one relationship. Multiple objects can subscribe to changes in a property of another object. As soon as that property changes, all objects subscribing to it will be notified

  • Implementation uses instance variables defined with properties to store the value of the property. When you assign a property it will call willChangeValueForKey: and didChangeValueForKey: to trigger the change broadcast to observers

  • The main point of entry into iOS apps is UIApplicationDelegate. UIApplicationDelegate is a protocol that your app has to implement to get notified about user events such as app launch, app goes into background or foreground, app is terminated, a push notification was opened, etc.

  • When an iOS app is launched the first thing called is application:willFinishLaunchingWithOptions:. This method is intended for initial application setup

  • The options identify if the app was called to handle a push notification or url or something else. Return true if your app can handle the given activity or url

  • Every time your app becomes active, applicationWillEnterForeground: is called

  • applicationWillResignActive:, applicationDidEnterBackground:, applicationWillTerminate:

  • Use View Controllers to get lifecycle callbacks for the view that the VC is managing and to get handy built-in system integrations to present and dismiss VCs using UINavigationController, modal presentation, or parent/child containment API

  • Lifecycle callbacks: viewWillAppear: viewDidAppear: viewWillDisappear: viewDidDisappear:

  • viewDidLoad(): gets called once when your VC's view was loaded in memory for the first time. Do any additional setup and initializations here. Most of your custom view initialization and autolayout set will go here. Also, start your services and other async data-related stuff here

  • Use viewWillAppear(): to do final UI customizations, hook up UI observers, etc.

  • We connect with backend APIs via HTTP

  • HEAD returns header information about a response

  • GET returns actual data for the resource your requested

  • POST posts something to your server

  • PATCH is used to change a resource's data

  • PUT replaces everything about the resource with the data you submit leaving on the unique ID intact

  • DELETE destroys a resource on the backend

  • Contracts between server and client were made for the purpose of not only convenience but consistency and predictability

  • REST is an API architecture that revolves around resources and HTTP verbs. Each resource is represented by a set of endpoints that can receive some of the HTTP verb requests to do various CRUD (Create, Read, Update, Destroy) operations

  • A service layer in your application usually has a networking/HTTP manager like NSURLSession, an APIClient object which actually performs HTTP requests against your API domain and is usually responsible for signing every request with authentication token/credentials, and a set of service objects that work with individual resources of your RESTful API

  • There are two ways you can issue HTTP requests with NSURLSession: either by receiving a completion handler block callback or by implementing delegate methods and receiving notifications as the data comes back

  • Don't block the main UI thread

  • NSJSONSerialization is the go-to tool for JSON dictionaries/arrays/primitives serialization

  • Map your objects into your custom domain model objects

  • You can use NSURLSession to download an image at a given URL as binary data, convert it from NSData to UIImage, and then display it in a UIImageView

  • In-memory cache could be as simple as a Dictionary that keeps reference to UIImage objects and uses the URLs they were downloaded from as unique keys or it could actually be NSCache that performs similar stuff for you and also can be configured

  • Database storage is used for image caching when you save downloaded image binary to Core Data or a similar database

  • NSCoding is a protocol for data serialization for data-storing operations with NSUserDefaults, NSFileManager, and Keychain

  • NSUserDefaults is a key-value storage that can persist serialized NSCoding compliant objects and primatives

  • Typically used for some locally stored user preferences and/or flags

  • It is not secure and does not persist between app installs

  • Keychain is a key-value store that is encrypted by the system and persists between app reinstalls

  • Core Data is an object graph and persistence framework

  • You need to serialize your data into NSManagedObjects before saving them to the Core Data database

  • GCRect is a struct that represents a rectangle that a view is placed at. It has an origin with x and y values, and a size with width and height values

  • The higher the compression resistance is, the less chance it's going to 'budge' under the other constraint's pressure to compress it

  • Hugging priority defines how likely is it the view will grow under pressure from other constraints

  • All UI changes have to be done on the main thread

  • frame, bounds, center, transform, alpha, and backgroundColor are all animatable with UIKit's animateWithDuration

  • Core Animation is used for more advanced animations

  • Using singletons to store a global state is never a good idea due to race conditions and other types of data overrides

  • The main purpose if the UI layer is to display UI elements on the screen and to take user input in and delegate it to the rest of your application

  • The service layer is responsible for all external communication your application has

  • The Single Responsibility Principle (SRP) states that every module should have only one responsibility and reason to change

  • The Open/Closed Principle states that your modules should be open for extension but closed for modification. 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 states that objects in a program should be replaceable with instances of their subtypes without altering the correctness of the program. When you inherit from a class or an abstract class or implement an interface, your objects should be replaceable and injectable wherever that interface or class that you subclassed from was used

  • The Interface Segregation Principle says many client-specific interfaces are better than one general-purpose interface. No client should be forced to depend on and implement methods it does not use

  • The Dependency Inversion Principle states, depend on abstractions, not concretions

  • When yyou create an object, you supply and inject all of its dependencies upon it's initialization or configuration rather than let the object create or fetch/find its dependencies for itself

  • The functional programming paradigm avoid mutability and state change

  • The Factory Method pattern is used to replace class constructors by abstracting and hiding object's initialization so that the type can be determined at runtime

  • The Adapter design pattern helps you adapt the interface of one object to the interface of another

  • The Decorator pattern 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

  • The Command design pattern has an object that represents an operation that you would like to execute and it has its own state and logic to perform on top of the underlying operation

  • The Template design pattern has 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

  • Typically we think of NSUserDefaults as a solution to store user settings or preferences or tokens

  • NSManagedObjects represent data stored in the database. You can think of them as model objects

  • NSManagedObjectContext allows you to insert, save, and retrieve NSManagedObjects from the database

  • NSFetchRequest is a query object that you use to retrieve NSManagedObjects from the database, optionally filtered with an NSPredicate and sorted with an NSSortDescriptor