Are you a Swift developer preparing for your next job interview? Look no further—this guide is exactly what you need. I’ve curated over 300 of the most commonly asked interview questions on iOS, Swift, UIKit, SwiftUI, and beyond, complete with recommended strategies for crafting your answers.
These are not just similar to what you might encounter—these are the very questions companies worldwide use in their interviews. Reviewing and practicing these questions is one of the best ways to ensure you’re ready.
After years of collecting and refining these questions, I’ve organized them into levels based on experience. In this post, I’m sharing some of the most frequently asked questions to help you confidently tackle your upcoming interview.
1. What is the difference between String and NSString?
In Swift String
is a struct, while in Objective-C, NSString
is a class and inherits from NSObject
. In concept, Swift String
is more likely immutable. If we use a struct type and constant (remember the let
keyword), we can keep out a lot of consideration of multi-thread programming and make a better life.
2. What is the Fallthrough statement?
The “fallthrough” statement in Swift is a keyword used in switch statements to transfer control from one case to another case, even if the preceding case has already been executed. This means that, when the “fallthrough” keyword is used, the code execution continues to the next case without checking the condition in the current case. The “fallthrough” statement is used to implement multiple cases with the same code logic or to continue executing code in a specific order in the switch statement.
3. What is the final keyword in Swift?
In Swift, the final
A keyword indicates that a particular entity (e.g., a class, method, or property) cannot be subclassed, overridden, or modified. Its usage can vary depending on the programming language, but the common concept is to enforce immutability or prevent further extension for specific elements in the codebase.
4. Different types of Access modifiers in Swift?
Access modifiers in Swift are keywords used to set the level of access for members (such as properties, methods, and initializers) of a class, structure, or enumeration.
Swift provides below access levels:
- open: the member can be used from any source file or module.
- public: the member can be used from any source file within the same module.
- internal: the member can be used from any source file within the same module (default access level).
- fileprivate: the member can only be used from the same source file it’s defined in.
- private: the member can only be used from within the same enclosing declaration (class, struct, enum).
5. What is Higher-Order-Function?
In Swift, a higher-order function is a function that takes one or more functions as input or returns a function as output. Higher-order functions allow you to abstract over actions, rather than just values.
For example, you can use the map
function to apply a transformation to each element in an array. The map
the function is higher-order because it takes a closure (a block of code that can be passed around as a value) as its input. Here’s an example of using the map
function:
let numbers = [1, 2, 3, 4]
let doubledNumbers = numbers.map { $0 * 2 }
// doubledNumbers is [2, 4, 6, 8]
In this example, the closure { $0 * 2 }
is a function that takes an Int
as input and returns an Int
. The map
the function applies this closure to each element in the numbers
array and returns a new array of the transformed elements.
Higher-order functions can be powerful and make your code more concise and expressive. They are an important concept in functional programming, a programming paradigm that emphasizes using functions to model computations.
6. What is an optional variable? In what ways you could Unwrap an optional?
In Swift, an optional variable is a variable that can either hold a value or be nil
, meaning it has no value. Optionals are a powerful feature that allows you to write safer and more robust code, by explicitly handling the case where a value may not be present.
There are several ways to unwrap an optional in Swift:
- Forced Unwrapping: This involves using the
!
operator to access the value of an optional. - Optional Binding: This involves using the
if let
statement to unwrap an optional, and bind the unwrapped value to a constant or variable. - Implicitly Unwrapped Optionals: This involves using the
!
operator after the type instead of after the variable name when declaring the optional. - Nil-Coalescing Operator: This involves using the
??
operator to provide a default value in case the optional isnil
.
7. What is Optional chaining?
Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil
. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil
, the property, method, or subscript call returns nil
. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil
.
For Example:
if let azharAddress = azhar.residence?.address?.street {
print("Azhar's street name is \(azharAddress).")
} else {
print("Unable to retrieve the address.")
}
// Prints "Unable to retrieve the address."
8. What is the difference between Guard and if-let statements?
Both guard
and if-let
serve important roles in Swift programming, ensuring safer handling of optionals and helping to manage control flow based on the state of optional values. Your choice between them depends on whether you need to exit the scope early due to a condition not being met (guard
), or if you need to conditionally unwrap and work with an optional value (if-let
).
9. What is the difference between Struct and Class?
In Swift, both structs and classes are used to define custom data types, but they have some important differences that make them suited for different use cases.
Here are some of the key differences between structs and classes:
- Inheritance: Classes support inheritance, which means that you can define a new class that inherits properties and methods from an existing class. Structs do not support inheritance.
- Mutability: Classes are reference types, meaning multiple variables can reference the same instance of a class. This also means that classes can be mutable, and changes made to one reference of a class instance will be reflected in all other references. Structs, on the other hand, are value types, which means that each instance is a unique copy of the data, and changes made to one instance do not affect other instances.
- Copying: When you pass a class instance to a function or assign it to a variable, you are passing a reference to the instance, not a copy of the data. This can lead to unexpected behaviour if the reference is modified inside the function or by another variable. With structs, when you pass an instance to a function or assign it to a variable, a copy of the instance is created, and any changes made to the copy do not affect the original instance.
- Initializers: Structs automatically generate a memberwise initializer, which allows you to initialize all the properties of a struct with a single initializer call. Classes do not automatically generate a memberwise initializer.
- Memory Management: Classes use reference counting to manage memory, which means that memory is automatically deallocated when there are no more references to a class instance. Structs, being value types, do not require reference counting and memory is automatically deallocated when the variable goes out of scope.
- Type: Structs are value types, while classes are reference types. This means that when you assign an instance of a struct to a variable or pass it as an argument to a function, a copy of the struct is made. With classes, the original instance is passed by reference, so any changes made to the instance are reflected in the original.
In general, you should use structs when you need to represent simple data types, and when you want to ensure that changes to one instance do not affect other instances. You should use classes when you need to represent more complex data types that require inheritance, or when you need to manage shared state between different parts of your program.
10. What is the difference between NSArray and NSMutableArray?
NSArray and NSMutableArray are two classes in the Foundation framework of the iOS SDK. The main difference between the two is that an NSArray is an immutable array, meaning its contents cannot be modified after it is created, while an NSMutableArray is a mutable array, meaning its contents can be modified after it is created. This means an NSMutableArray has methods for adding, removing, and modifying elements, while an NSArray does not.
11. What is the difference between Objective C and Swift?
Detail comparison here.
12. What’s the difference between a static variable and a class variable?
Both the static
and class
keywords allow us to attach variables to a class rather than to instances of a class.
Where static
and class
differ in how they support inheritance: When you make a static
property it becomes owned by the class and cannot be changed by subclasses, whereas when you use class
it may be overridden if needed.
Here’s a quick summary:
- Static Variables: Not subclassable, shared across all instances and the type itself.
- Class Variables: Subclassable, each subclass can provide its value.
13. Different types of initializers available in Swift?
In Swift, you can initialize a new instance of a type using an initializer. There are several types of initializers that you can use, including:
- Default Initializers: These initializers are provided automatically by the Swift compiler for certain types, and are used to create a new instance of that type with all of its properties set to their default values.
- Memberwise Initializers: These initializers are provided automatically by the Swift compiler for structs, and are used to initialize a new instance of the struct by assigning initial values to each of its properties.
- Failable Initializers: These initializers can fail to initialize an instance of a type, and are indicated by placing a question mark (?) after the init keyword.
- Required Initializers: These initializers are initializers that must be implemented by any subclass of a class that defines them. They are indicated by the “required” keyword.
- Convenience Initializers: These initializers are secondary, supporting initializers for a class. They are indicated by the “convenience” keyword.
- Custom Initializers: These are initializers that you can define yourself to provide customized initialization for your types. You can define custom initializers for classes, structs, and enums.
- Designated Initializer: A designated initializer is the primary initializer for a class. It initializes all properties introduced by that class and calls the superclass’s designated initializer.
- Implicitly Unwrapped Optional Initializer: ties that are declared as implicitly unwrapped optionals.
14. What is the difference between Function and Method?
In Swift, a function is a self-contained block of code that performs a specific task. It can take input in the form of arguments and can return a value or output to the caller. Functions can be defined at the global scope, within a class or struct, or even nested within another function.
A method is a special kind of function that is associated with a particular type, such as a class or struct. In other words, a method is a function that is a member of a type. Methods can be called on instances of the type, and can access and modify the properties of those instances.
Here’s an example to help illustrate the difference between a function and a method in Swift:
struct Point {
var x: Double
var y: Double
// This is a method on the Point struct. It is called on an instance of Point.
func distanceToOrigin() -> Double {
let dx = x - 0
let dy = y - 0
return sqrt(dx * dx + dy * dy)
}
}
// This is a function that is not associated with any particular type.
func printDistance(point: Point) {
let distance = point.distanceToOrigin()
print("The distance to the origin is: \(distance)")
}
In this example, the distanceToOrigin()
method is a member of the Point struct and can be called on instances of Point. The printDistance
function is not associated with any particular type and can be called with any value of type Point
.
15. What’s the nil coalescing operator in Swift and what is used for?
The nil coalescing operator (??
) in Swift is used to provide a default value for an optional variable when it is nil
. It is a shorthand way of unwrapping an optional and returning a default value if the optional is nil
.
The nil coalescing operator can also be used to provide a default value for an optional in a more complex statement. Here is an example:
let optionalName: String? = nil
let defaultName = "Azhar Khan"
let name = optionalName ?? defaultName
let greeting = "Hello, \(name)"
print(greeting) // Output: "Hello, Azhar Khan
"
In this example, if the optionalName
is nil
, the defaultName
is returned instead, and the greeting
will be “Hello, Azhar Khan”
The nil coalescing operator is useful when you want to use a default value for an optional variable without having to check if it is nil
first. It makes your code more readable and concise.
16. Different types of Properties in Swift?
In Swift, there are two main types of properties:
- Stored Properties: These are properties that store a value assigned to them as a constant or a variable. They are declared with the ‘var’ or ‘let’ keyword and are associated with a specific instance of a class or structure.
- Computed Properties: These properties do not store a value but instead provide a getter and an optional setter to retrieve and set other properties or values dynamically. They are declared using the ‘var’ keyword but do not have an explicit value assigned to them.
Additionally, Swift properties can also be further classified based on their access level, memory management, and other attributes, such as:
- Lazy Stored Properties: These properties are not initialized until they are accessed for the first time, and their value is stored for future use.
- Observed Properties: These properties are monitored for changes and action is taken when their value is changed.
- Read-only Computed Properties: These properties have only a getter, and their value cannot be set.
- Property Wrappers: These properties are used to encapsulate the implementation details of a property and provide a higher level of abstraction.
17. How to manage mutable and immutable Array in Swift?
In Swift, arrays are implemented as a struct, which means they are immutable by default. To create a mutable array, you can use the “var” keyword when declaring the array. For example:
var myArray = [1, 2, 3]
To create an immutable array, you can use the “let” keyword when declaring the array. For example:
let myArray = [1, 2, 3]
You can use the `var` keyword to create a mutable array and the `let` keyword to create an immutable array. Once an immutable array is created, you can’t add, remove, or modify its elements, and any attempt to do so will result in a compile error. If you need to modify an immutable array, you can create a new array with the desired modifications
18. What is a selector in Swift?
A selector is a type used to identify a method or function that can be called at runtime. It’s used to specify the method or function that should be called when a certain event occurs, such as a button press or a notification.
A selector is represented as a String, and it’s the name of the method or function that you want to call. For example, the following selector refers to a method called “buttonPressed”:
#selector(buttonPressed)
Selectors can be used in various parts of iOS development, such as when setting the target-action pattern for control like UIButton
or UIBarButtonItem
, or when registering for notifications.
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
In this example, when the user touches the button and releases it, the buttonPressed method will be called.
It’s important to note that the method or function identified by the selector must be marked with the @objc attribute, otherwise, the app will crash when trying to call it.
19. Different types of Application States in iOS
In iOS, an app can transition through several different states as it interacts with the user and the system. These application states dictate how the app responds to various events and how it manages resources. Understanding these states is important for designing responsive and efficient apps. Here are the different types of application states:
- Not Running: The app has not launched or has been terminated.
- Inactive: The app is in the foreground but not receiving events.
- Active: The app is in the foreground and actively receiving user input.
- Background: Certain tasks can continue to be executed in the background, such as playing audio or tracking location.
- Suspended: The system may move apps to this state to free up resources.
- Terminated: The app is not running at all. It has been terminated by the user or the system.
20. What is Tuple? Where you can use it.
In Swift, a tuple is a type that allows you to group multiple values of different types into a single compound value. A tuple can have any number of elements, and each element can have a different type.
A tuple can be created by enclosing the values inside parentheses and separating them with commas. For example:
let person = (name: "Azhar", age: 28)
You can access the elements of a tuple by using their index or by using named fields. For example, you can access the name of the person in the example above by using:
let name = person.name
or by using
let name = person.0
21. What is the difference between a weak and strong reference?
In Swift, a reference is a way to refer to an object, and it’s an important concept in memory management. There are two types of references: strong and weak.
A strong reference is a reference that keeps the object it refers to alive in memory. As long as there is at least one strong reference to an object, the object will not be deallocated by the Swift runtime’s Automatic Reference Counting (ARC) system.
A weak reference, on the other hand, does not keep the object it refers to alive in memory. A weak reference does not increase the reference count of an object, which means that if there are no other strong references to the object, the object will be deallocated by the ARC system.
22. What is the difference between Array and Tuple?
In Swift, an array and a tuple are both types that allow you to group multiple values, but they have some important differences.
An array is an ordered collection of values. It is a mutable data type, which means that you can change the contents of an array once it is created. An array can contain elements of any type, and the size of an array is not fixed.
A tuple is also an ordered collection of values, but it is an immutable data type, which means that you cannot change the contents of a tuple once it is created. Like an array, a tuple can contain elements of any type. However, the size of a tuple is fixed, and you cannot add or remove elements from a tuple.
Here are some key differences between arrays and tuples in Swift:
- Mutability: Arrays are mutable, while tuples are immutable.
- Size: The size of an array is not fixed, while the size of a tuple is fixed.
- Modification: You can modify the contents of an array, but you cannot modify the contents of a tuple.
Overall, arrays are more flexible than tuples because they are mutable and their size is not fixed. However, tuples are useful when you need to group a fixed number of related values and you don’t need to modify those values.
23. What is the role of AppDelegate in an iOS app?
The AppDelegate in an iOS app is a central point of control for the app. It is responsible for handling certain important events in the app’s lifecycle, such as when the app is launched, when it enters the background, and when it is terminated. The AppDelegate also manages the app’s window and root view controller and can be used to perform other tasks such as configuring the app’s navigation bar or handling remote notifications.
24. What is the difference between a weak and strong reference?
“Passing by value” and “passing by reference” are two different ways that programming languages handle the transfer of data between functions or methods. These concepts refer to how variables are shared or copied when they are passed as arguments to functions. Let’s explore both concepts:
- Passing by Value:
- In passing by value, a copy of the actual data is made and passed to the function. The function receives its copy of the data, and any changes made to the data inside the function do not affect the original data outside the function.
- This is typically used for simple data types like integers, floating-point numbers, booleans, and structs (in some languages).
- Changes made to the function’s parameter do not affect the original variable.
- It’s as if you handed someone a photocopy of a document. Any changes they make to the copy do not affect the original document.
- Passing by Reference:
- In passing by reference, a reference to the actual data (memory location) is passed to the function. The function operates directly on the original data, and changes made to the data inside the function will affect the original data outside the function.
- This is commonly used for complex data types like arrays, objects, and classes.
- Changes made to the function’s parameter affect the original variable as well.
- It’s like giving someone access to the original document. Any changes they make directly affect the original document.
25. What is Computed Property?
A computed property is a property in a programming language that doesn’t store an actual value but provides a mechanism to calculate a value dynamically based on other properties or logic. Instead of storing a value directly, a computed property contains a getter method that calculates the value whenever the property is accessed. Computed properties are a powerful feature that allows you to encapsulate complex calculations and provide a simple interface for accessing their results.
Where To Go Next – Part 2 ⏩
Thanks for reading! I hope this will be useful for understanding or refreshing some of the iOS concepts. Please share your feedback, and queries regarding any of the topics in the comments below. Till then happy Coding!!! 💚💚💚💚💚💚💚💚💚💚