Crack Your iOS Interview: Top Questions You Must Know in 2023 Before You Go!”

ShreeThaanu Raveendran
9 min readMar 15, 2023

--

I know you have been looking about so much of blogs in upscaling yourself in 2023, Right now i can just curate few of a questions and skills what interviewers think is a must knowledge in iOS. This Blog will be coming in 2 parts. This one deals with basic topics and the next one will have the core swift, iOS and Xcode topics.

Starting with basics part

Value types and Reference types :

  • A value type instance keeps a unique copy of its data, for example, a struct, enum, tuple.
  • A reference type, shares a single copy of its data, so that every new instance will point to the same address in memory and the type is usually a class.

When to Use Value Types :

  • Use value types when comparing instance data with == makes sense.
    == checks if every property of the two instances is the same.
    With value types you always get a unique, copied instance, and you can be sure that no other part of your app is changing the data under the hood.
  • This is especially helpful in multi-threaded environments where a different thread could alter your data.
  • Use a value type when you want copies to have an independent state, and the data will be used in code across multiple threads.
  • In Swift, Array, String, and Dictionary are all value types.

Reference Types

In Swift, reference type instances share a single copy of their data, so that every new instance will point to the same address in memory. A typical example is a class, function, or closure

When to Use Reference Types:

  • Use a reference type when comparing instance identity with === makes sense. === checks if two objects share the same memory address.
  • They’re also useful when you want to create a shared, mutable state.
  • As a general rule, start by creating your instance as an enum, then move to a struct if you need more customization, and finally move to class when needed.

One of the primary reasons to choose value types over reference types is the ability to more easily reason about your code. If you always get a unique, copied instance, you can trust that no other part of your app is changing the data under the covers. This is especially helpful in multi-threaded environments where a different thread could alter your data out from under you. This can create nasty bugs that are extremely hard to debug.

Struct vs class

Structures and classes are good choices for storing data and modeling behavior in your apps, but their similarities can make it difficult to choose one over the other.

Consider the following recommendations to help choose which option makes sense when adding a new data type to your app.

  • Use structures by default.
  • Use classes when you need Objective-C interoperability.
  • Use classes when you need to control the identity of the data you’re modeling.
  • Use structures along with protocols to adopt behavior by sharing implementations.

( Refer to Apple doc for more detailed)

Memory management in iOS / ARC

Your iOS app needs to know which data it can free from memory, to make space for new data. The most effective way to manage memory is to keep track of which objects are being used, and if no one is using an object, to remove it from memory. ARC only affects reference types, like classes. It does not affect value types, like structs. Value types are copied when they’re passed/referenced, so beyond the local scope there’s nothing to retain in memory.

Strong :

Strong references increase the retain count of instances they reference (by 1). This prevents the Automatic Reference Counting (ARC) from removing the object from memory, as long as the object is in use. strong references are the default

Weak :

To make a reference weak you can use the weak keyword. Unlike strong references, a weak reference does not affect an instance’s retain count. It does not hold onto the object.

why we have weak references at all. You already know we need ARC to manage memory, and we need to manage memory to know what data to remove to free up space. The only reason you need to use weak in Swift coding is to avoid strong reference cycles.

In short, a strong reference cycle or “retain cycle” is 2 instances holding onto each other. They cannot be removed from memory, which causes a memory leak, which could crash your app, which is a bad user experience. We’ll focus on resolving strong reference cycles in the next and last tutorial in this series.

  • You can mark a reference as weak with the weak keyword. The default is strong, hence usage of the weak keyword. A weak property must be an optional, as well. Otherwise it cannot be nil.
  • An instance’s retain count is not affected by a weak reference, as opposed to a strong reference. Beyond an instance’s existing retain count, a weak reference does not keep the instance in memory.

Higher order functions

A higher-order functions takes one or more functions as arguments or returns a function as its result. Below are the higher-order functions provided by the Swift language

  • map() : perform an operation on all the elements of a collection and returning a new collection with the results of that operation.
let numbersInString = numbers.map { number in String(number) }
  • compactMap() : returns an updated array only containing elements that satisfy the condition stated within its body.
let numbersInString = ["1", "x2", "3", "4", nil, "five5"] 
let validNumbers = numbersInString.compactMap { stringValue in Int(stringValue ?? "") }

  • flatMap() : allows us to transform a set of arrays into a single set that contains all of the elements.
let numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let result = numbers.flatMap({ $0 })
  • filter() : iterate through all elements in an array and will return an updated array only with the elements which satisfy the condition.
let numbers = [-12, 23, -1, 56, 9, -2, 0, 14, 8].filter { number in number > 0 }
  • reduce() : iterate through all elements in an array and return an object with the combined value of all elements.
let numbers = [1, 5, 2, 10, 6].reduce(0) { 
(result, number) -> Int in result + number
}
  • sort() : return a sorted value.
var numbers = [1, 5, 2, 10, 6] numbers.sort()

(More about higher order function)

Size classes:

Size Classes are the methods for creating adaptable layouts that look great on all sizes and orientations of iPhone and iPad. For example, you might want to say that your UI looks mostly the same in portrait and landscape, but on landscape some extra information is visible. (More about Size class)

  • GCD/Operation queue’s

View Life cycles:

View controllers are the foundation of the Application’s internal structure. This is a map of how VC works in iOS. They are the skeleton of the VC cycle and thats how the app responds.

Property wrappers

These adds a layer of separation between code that manages how a property is stored and the code that defines a property. For example, if you have properties that provide thread-safety checks or store their underlying data in a database, you have to write that code on every property.

Defer

Defer takes in a block of code to execute when the execution leaves the current scope. defer can be used like the following syntax.

defer { 
print("Step 3")
}

Lazy:

A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

lazy var oldest: Person? = {
return people.max(by: { $0.age < $1.age })
}()

Guard vs if let:

if let and guard let serve similar, but distinct purposes. The “else” case of guard must exit the current scope. Generally that means it must call return or abort the program. guard is used to provide early return without requiring nesting of the rest of the function.

if let nests its scope, and does not require anything special of it. It can return or not.

guard let array = optionalArray else {
return 0 }

if let string = value {
return string
}

Storyborad vs SwiftUI :

Storyboard and SwiftUI are 2 different means of creating a UI. storyboards work in a visual representation of interfaces and can have a collection of VC with segues and drag and drop. Incase of SwiftUI its a code based UI Builder where you can see the views you build in side.

SwiftUI has a limitation of deployment target as iOS 13 and storyboard is a heavy weight substance also comes with issues when workin on GIT. SwiftUI is pretty new so there are edge case issues developers been facing till now, on the other hand storyboard can be a mess when comes to building for multiple devices. Animation and other stuff became cooler when swiftUI is introduced.

If your mid/senior level engineer, here are few additional topics you have to cover

TDD:

Test driven development is the most preferred programming way in Tier1 companies. It’s a practice by which you start with the test cases and then work on functions. In short its like Red Green mechanism, Write the testcases — fail them and pass them by the logic. By this you would know all edge cases are covered. In my alst 3 years of TDD, i agree its a time consuming but a worthy way for development. Test cases for every logical class can give a insight of the forecasting error. In iOS, we use XCTestCases for this.

A sample test can be as follows.

final class StringExtensionsTests: XCTestCase {
func testUppercaseFirst() {
let input = "antoine"
let expectedOutput = "Antoine"
XCTAssertEqual(input.uppercasedFirst(), expectedOutput, "The String is not correctly capitalized.")
}
}

func uppercasedFirst() -> String {
let firstCharacter = prefix(1).capitalized
let remainingCharacters = dropFirst().lowercased()
return firstCharacter + remainingCharacters
}

Instruments:

Xcode Instruments are used to Identify Performance Problems, record observation and monitor the application in both the development and deployed state. Instruments can give a fix for your solution, It gives a insight over your problem, have an idea of what you exactly you have to identify because instruments is huge and there is a high chances you may get lost. Few of my favourite Instruments are

Profiler: Profiler helps you in debugging network, memory, coredata based profiling. You can identify the load time, data balance, serial queue issues and far more like them. among them time profiler is my favourite, they help in inspecting stack traces and time spent in each functions

Zombies: These are the plot issues happening in iOS, like the way memory problem are and the crash can be identified on the VC. These can also identify the cell reducing allocation, Cache and more.

Leaks: They show you the memory leak happening, any reference of the object thats still one the memory and not deallocated after its life would be caught here.

Animation hitches: Application performance on Rendering cells, UI Animation are any kind of animation performance can be found here, So you can handle in more efficient way.

App launch: These provides statistics on app launch times, There are instances where app takes too much times to load like watch dog exception takes too much time, kill it.

Compiler level Debugging:

What distinguish between a developer and senior developer is the way we debug things, Looking into a issue directly and expecting to find a solution is not a right way, according to me its a hack kindah thing. But understanding the stack-trace behind the compiler-generated is the better way.

Xcode compiler takes the project source and forms a tree-like structure to define the dependencies of modules. It then goes compiling with a bottom-up approach

i.e. compiling the modules with least dependencies first. Understanding the cause of the error and fixing it in proper way can avoid more future mistakes.

Build, Architect or Kick start an App from scratch :

Refer to my blog about how to build an App from scratch, What are the questions you have to ask the client, How to decide with given documentation and many more questions are answered.

https://shreethaanur.medium.com/what-i-wish-i-knew-as-a-fresher-about-building-ios-app-from-scratch-912a01418552

Dependency Injection:

This is a method by which you define contracts for an object ,classes and by using those contracts inject multiple types of object.

Design patterns :

I have written a 3 part Article about this Please do refer it.

iOS Security features :

I have discussed quite a good amount regarding security features in iOS and what can be used depending on projects.

My Security Blog : https://shreethaanur.medium.com/fortifying-your-ios-swift-app-essential-security-measures-to-keep-your-users-safe-d686c79ae4a3

Follow me on other social networks too.

LinkedIn: https://www.linkedin.com/in/shreethaanu-raveendran-7a6275b2/

Github : https://github.com/shreethaanu

Instagram : https://www.instagram.com/shreethaanu_blogs/

Portfolio : https://strlabz.com

Patreon : https://www.patreon.com/shreethaanu

If you like my post and wanna see more support me ☕️

--

--

ShreeThaanu Raveendran

Apple Platforms Developer | XR Researcher | DesignTechnologist