Yandex iOS Interview Notes

I applied for Yandex Internship as an iOS developer and passed the tech interview. Here are the notes that I used to prepare for it.

Alex Dremov
Yandex iOS Interview Notes

Photo by Juja Han / Unsplash


  • Syntax
  • Basic structures
  • Arrays, collections
  • Closures
  • Passing parameters to closures
  • Errors — find, describe outcomes, solve

Check information about @autoclosure, indirect, lazy, and other keywords. Try to Google tests on Swift knowledge and check yourself.

Alex Dremov | Top 7 Subtle Swift Features
Here, I collected Swift features that are less known and can be useful when you prepare for interviews or want to deepen your Swift knowledge.

Protocols conformance knowledge was usefull. Note which protocols are automatically generated for enums, structures; when do they break?

Understending of ARC and how Swift memory management works is required. Is closure value type or reference type? How weak modifier works under the hood?


Basic overview. There should be no magic on how the app launches

App life cycle

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
    	return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
State Description
Not running The app is not running.
Inactive The app is running in the foreground, but not receiving events. An iOS app can be placed into an inactive state, for example, when a call or SMS message is received.
Active The app is running in the foreground, and receiving events. Transitional state.
Background The app is running in the background, and executing code.
Suspended The app is in the background, but no code is being executed. App is still in memory
Method Description
application:willFinishLaunchingWithOptions This method is your app’s first chance to execute code at launch time.
application:didFinishLaunchingWithOptions This method allows you to perform any final initialization before your app is displayed to the user.
applicationDidBecomeActive The app has entered the foreground app. Use this method for any last minute preparation.
applicationWillResignActive The app is transitioning away from being the foreground app.
applicationDidEnterBackground The app runs in the background and may be suspended at any time.
applicationWillEnterForeground The app moves out of the background and back into the foreground, but that it is not yet active.
applicationWillTerminate The app is being terminated. This method is not called if your app is suspended.
Every iOS application needs at least one window—an instance of the UIWindow class—and some may include more than one window


I almost failed on that one


  • viewDidLoad()
    Called after init(coder:) when the view is loaded into memory
    Note that just because the view has been loaded into memory doesn’t necessarily mean that it’s going to be displayed soon – for that, you’ll want to look at viewWillAppear
  • viewWillAppear(_:)
    Always called after viewDidLoad (for obvious reasons, if you think about it), and just before the view appears on the screen to the user, viewWillAppear is called
  • viewWillDisappear(_:)
    Similar to viewWillAppear, this method is called just before the view disappears from the screen
  • loadView()
    This event creates the view that the controller manages. It is only called when the view controller is created programmatically. You can override this method in order to create your views manually. If you are working with storyboards or nib files, then you do not have to anything with this method and you can ignore it.
  • loadViewIfNeeded()
    Loads the view controller’s view if it has not already been set. available from iOS >=9.0
  • viewDidLoad()
    Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set. Use this method to initialize setup of the interface
  • viewWillAppear(_ animated: Bool)
    This method will get called every time the view is about to appear, whether or not the view is already in memory.
  • viewWillLayoutSubviews()
    Called just before the view controller’s view’s layoutSubviews method is invoked. This is the first step in the lifecycle where the bounds are finalised. If you are not using constraints or Auto Layout you probably want to update the subviews here.
  • viewDidLayoutSubviews()
    Called just after the view controller’s view’s layoutSubviews method is invoked. This event notifies the view controller that the subviews have been setup.
  • viewDidAppear(_ animated: Bool)
    Called when the view has been fully transitioned onto the screen.
  • viewWillDisappear(_ animated: Bool)
    This method will get called when the view controller’s view is about to be removed from the view hierarchy.
  • viewDidDisappear(_ animated: Bool)
    This method will get called when the view controller’s view was removed from the view hierarchy.
Subscribe and don't miss posts!


View controller has one root view, which is a UIView instance

  • UIViewController handles all the magic behind UIView while UIView just represents the screen and some content to the user. UIViewController tells the root UIView object when to come to the screen. First, the view controller creates its root view and loads it. After loading, it tells the view to appear on the screen and disappear when necessary.
  • didAddSubview(_:)
  • willRemoveSubview(_:)
  • willMove(toSuperView:)
  • didMoveToSuperview()
  • willMove(toWindow:)
  • didMoveToWindow()

UIKit basics


  • An abstract interface for responding to and handling events.
  • In UIKit, all view layers have options for shadow opacity, radius, offset, color, and path

Layout Principles

There are actually three phases associated with the layout and drawing of the views.

  1. The first is update of constraints (constraint pass), which happens bottom up.
  2. The second is layout of views and subviews (layout pass), which happens top down and is dependent on constraint settings.
  3. The third phase is the display pass, where the views get redrawn based on the layout pass.

Auto Layout dynamically calculates the size and position of all the views in your view hierarchy, based on constraints placed on those views



let views = [
	"icon": iconView,
    "titleLabel": titleLabelView,
    "postDate": postDateView

	withVisualFormat: "H:|-[icon(==postDate)]-20-[titleLabel(120@250)]-20@750-[postDate(>=50)]-|",
    metrics: nil,
    views: views


extension UIView {
    open var leadingAnchor: NSLayoutXAxisAnchor { get }
    open var trailingAnchor: NSLayoutXAxisAnchor { get }
    open var leftAnchor: NSLayoutXAxisAnchor { get }
    open var rightAnchor: NSLayoutXAxisAnchor { get }
    open var topAnchor: NSLayoutYAxisAnchor { get }
    open var bottomAnchor: NSLayoutYAxisAnchor { get }
    open var widthAnchor: NSLayoutDimension { get }
    open var heightAnchor: NSLayoutDimension { get }
    open var centerXAnchor: NSLayoutXAxisAnchor { get }
    open var centerYAnchor: NSLayoutYAxisAnchor { get }
    open var firstBaselineAnchor: NSLayoutYAxisAnchor { get }
    open var lastBaselineAnchor: NSLayoutYAxisAnchor { get }

let constraints = [
	view.centerXAnchor.constraint(equalTo: superview.centerXAnchor),
	view.centerYAnchor.constraint(equalTo: superview.centerYAnchor),
	view.widthAnchor.constraint(equalToConstant: 100),
	view.heightAnchor.constraint(equalTo: view.widthAnchor)


In the core

GCD, OperationQueue

  • OperationQueue internally uses Grand Central Dispatch and on iOS.
  • OperationQueue gives you a lot more control over how your operations are executed. You can define dependencies between individual operations for example, which isn't possible with plain GCD queues. It is also possible to cancel operations that have been enqueued in an OperationQueue (as far as the operations support it). When you enqueue a block in a GCD dispatch queue, it will definitely be executed at some point.
  • To sum it up, OperationQueue can be more suitable for long-running operations that may need to be cancelled or have complex dependencies. GCD dispatch queues are better for short tasks that should have minimum performance and memory overhead.

I already had in-depth understanding of how GCD works. Yf you don't feel confident in this area, defenitely check some topics on it. That's really crucial part of iOS development


  • userInteractive
    We use this for UI updates, event handling and small workloads that require low latency
  • userInitiated
    The user initiates these asynchronous tasks from the UI. We can use this when the user is waiting for results and for tasks which are required to continue user interaction. This run in the high priority global queue.
  • utility
    This represents long-running tasks such as a progress indicator which is visible during computations, networking, continuous data fetching, etc. This run in the low priority global queue.
  • background
    This represents tasks that users are not aware of such as prefetching, maintenance, and other tasks that don’t require user interaction and aren’t time-sensitive. As I mentioned, this has the lowest priority.


let url = URL(string: "")!

let task = URLSession.shared.dataTask(with: url) {(data, response, error) in 
	guard let data = data else { return }
	print(String(data: data, encoding: .utf8)!)
    // Global queue
let url = URL(string: "")!

let session = URLSession.shared var request = URLRequest(url: url) 
request.setValue("application/json", forHTTPHeaderField: "Content-Type") 
request.httpMethod = "GET"

session.dataTask(with: request) { (data, response, error) in 
    // Global queue



  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation
  • Dependency Inversion


  • Model View Controller
  • Drawback: not every element can fit into these three groups


  • Model View ViewModel



Subscribe to Alex Dremov

Get the email newsletter and receive valuable tips to bump up your professional skills