Apple introduced the Swift programming language in 2014 as a modern, safe, and fast language designed to be easy to learn and use. It combines elements from various programming languages, such as Objective-C, C, Python, and others, while introducing new features and capabilities.
While it is primarily used for iOS and macOS development, it is also gaining popularity for cross-platform development.
There is a high demand for skilled Swift developers, so learning it will open up opportunities for career growth in iOS app development, one of the fastest-growing sectors in the tech industry. This blog will discuss Swift's 10 most commonly asked interview questions.
In Swift, let
and var
keywords are used to declare constants and variables, respectively.
We declare a constant using the let
keyword. Because a constant cannot be changed after being initialized, we must assign it a value when it is declared.
let standard = 100.1let name: String = "John"print("Printing float value ",standard)print("Printing string value ",name)//standard = 200.2//print("Printing float value after change",standard)
Line 1: We declare a constant named standard
that contains a floating point value.
Line 2: We declare a constant named name
that contains a String
value.
Lines 4–5: We print their values.
Note: Try uncommenting the code in lines 6–7 and execute the code. We will get a compilation error that we cannot assign a value to a constant.
We declare a variable using the var
keyword. The value assigned to a variable can be changed at any time. A variable can be declared without an initial value and assigned later.
var standard = 100.1var name: String = "John"print("Printing float value ",standard)print("Printing string value ",name)standard = 200.2name = "Educative"print("Printing float value after change",standard)print("Printing string value after change",name)
Lines 1–2: We declare two variables named standard
and name
.
Lines 4–5: We print the values for the standard
and name
variables.
Lines 7–8: We reassign the values to variables.
Lines 10–11: We print the values of the variables standard
and name
again after making the changes.
Type inference is a feature that allows the compiler to automatically deduce the data type of a variable or constant based on the initial value assigned to it. This makes the code cleaner and more concise code without sacrificing type safety. It is especially useful when working with complex data types like arrays or dictionaries where explicitly specifying types may be cumbersome.
let number1 = 100let number2 = 200.356var message = "Educative"print(type(of: number1))print(type(of: number2))print(type(of: message))
Lines 1–3: We declare three variables: number1
, number2
, and message
. We assign them integer, floating point, and string values, respectively.
Lines 5–7: We print the data type of the three variables using the function type(of : variable)
.
When we execute the code, we see the data types printed as Int
, Double
, and String
.
A tuple is a lightweight data structure that can group multiple values into a single compound value. It can hold any combination of values of different types. They are commonly used in Swift for functions that need to return multiple values or when working with APIs that return multiple values. They provide a convenient way to group related values without defining a custom data structure like a class or struct.
let sampleTuple = (1000, "Educative", true)let val1 = sampleTuple.0let val2 = sampleTuple.1let val3 = sampleTuple.2print("Printing values using index of elements of the tuple.")print(val1);print(val2);print(val3);let namedTuple = (age: 22, name: "John")let age = namedTuple.agelet name = namedTuple.nameprint("Printing values using named elements of tuple.")print(age);print(name);
Lines 1: We create a tuple named sampleTuple
with three values.
Lines 2–4: We access the tuple's values using the index of elements.
Lines 5–8: We print the values retrieved using the dot notation.
Line 10: We create a tuple, namedTuple
, with named elements.
Lines 11–12: We access the values of the tuple using the name of the elements.
Line 13–15: We print the values retrieved using the named elements.
There are two comparison operators in Swift: ==
and ===
.
The ==
operator checks whether two values are equal in content. It performs a value check of the variables or constants being compared. It is commonly used to compare built-in types like Int
, String
, Double
, etc. However, it can also be used to compare instances of custom types if they conform to the Equatable protocol.
let a = 5let b = 5if a == b {print("They are equal")}struct Student: Equatable{var age: Intvar name: String}let student1 = Student(age:22, name:"John")let student2 = Student(age:22, name:"John")let student3 = Student(age:25, name:"John")if student1 == student2 {print("student1 and student2 are equal")}if student2 == student3 {print("student2 and student3 are equal")}
Lines 1–5: We declare two variables, a
and b
, and print a message only if they are equal.
Lines 7–10: We create a struct named Student
with two values: age
and name
. It conforms to the Equatable
protocol.
Lines 12–14: We create three student objects with student1
and student2
having the same age and name and student3
with a different age
.
Lines 16–18: We compare student1
and student2
and print a message only if they are equal.
Lines 20–22: We compare student2
and student3
and print a message only if they are equal.
The ===
operator checks whether two variables or constants refer to the same memory instance. It is also called the identity operator. It is mostly used for classes and functions to check if two references point to the same instance.
class Student {}let student1 = Student()let student2 = student1if student1 === student2 {print("They are the same objects.")}
Lines 1–2: We create an empty Student
class.
Line 3–4: We create a Student
object named student1
and then create a new object, student2
, which points to student1
.
Lines 6–8: We compare the two objects using the identity operator and print a message if they are equal.
The for-in
loop is used to iterate over a sequence or collections such as arrays, sets, dictionaries, etc. We can execute a set of statements for each item in the sequence. It can also be used to access the index and value of each item in an array using the enumerated()
method.
let countries = ["USA", "Canada", "England"]for country in countries {print(country)}for (index, letter) in "Educative".enumerated() {print("Index \(index) has letter \(letter) ")}
Line 1: We create an array containing names of countries.
Lines 2–4: We traverse the array using the for-in loop and print its elements individually.
Lines 6–8: We traverse the word Educative
and print every index and letter at that index.
We can define closures as self-contained blocks of functionality that can be passed around and used in a code. They are very similar to lambdas in other programming languages. We can capture and store references to constants and variables from the context in which closures are defined.
////////////Example 1////////////////////////////let multiply = { (val1: Int, val2: Int) -> Int inreturn val1 * val2}print(multiply(5, 100))////////////Example 2////////////////////////////func transform(_ numbers: [Int], with logic: (Int) -> Int) -> [Int] {var result = [Int]()for number in numbers {let transformedValue = logic(number)result.append(transformedValue)}return result}let numbers = [11, 21, 31, 41]let modifiedNumbers = transform(numbers) { $0 * 2 }print(modifiedNumbers)
Lines 2–4: We create a closure multiply
that takes two values and multiplies them with each other.
Line 5: We call the closure and print its result.
Lines 8–15: We define a function transform
that takes an integer array and a closure that defines how to transform each element.
Line 16: We create an array of integer numbers.
Line 17: We call the function transform
by providing an integer array and using the shorthand closure syntax. We define the closure such that it will multiply every value with 2.
Line 18: We print the returned array from the function.
A protocol is a contract of methods, properties, and other requirements that suit a particular functionality. Classes, structures, and enumerations may conform to a protocol to provide an actual implementation of these requirements. We can consider them as interfaces in other programming languages. Using protocols enhances the code flexibility and reusability.
protocol Info {var name: String { get set }var age: Int { get set }func printBio()}class Student: Info {var name: Stringvar age: Intinit(name: String, age: Int) {self.name = nameself.age = age}func printBio() {print("Student's name is \(name) and he is \(age) years old.")}}let student = Student(name: "John", age: 20)student.printBio()
Lines 1–5: We define a protocol, Info
, with two properties name
and age
, and a method printBio
.
Lines 7–19: We create a Student
class that conforms to the Info
protocol. We provide the implementation for the method printBio
.
Line 20: We create a student object with a name John
and age 20
.
Line 21: We call the method printBio
of the student object.
The double question mark ??
in Swift is called the nil-coalescing operator. It provides a precise way to provide a default value for an optional if nil. Suppose we have the expression x ?? y
. Then expression evaluates to the value of x
if x
is not nil and the expression evaluates to the value of y
if x
is nil.
let x: Int? = nillet y = 100let result = x ?? yprint(result)
Generics allow us to write flexible and reusable functions, structures, classes, and enumerations that can work with any type. We can write code that avoids duplication by abstracting types and logic away from specific implementations like templates in other programming languages.
func swapValues<T>(_ a: inout T, _ b: inout T) {let temp = aa = bb = temp}var x = 5var y = 10print("Before swap x = \(x) and y = \(y)")swapValues(&x, &y)print("After swap x = \(x) and y = \(y)")var greeting = "Hello"var company = "Educative"print("Before swapping greeting = \(greeting) and company = \(company)")swapValues(&greeting, &company)print("After swapping greeting = \(greeting) and company = \(company)")
Lines 1–5: We define a generic function swapValues
, that can swap the values of any two variables regardless of their data type.
Lines 7–8: We create two variables and assign them integer values.
Lines 9–11: We print the values of the string variables before swapping. Then, we call the swapValues
function and print the values again.
Lines 13–14: We create two variables and assign them string values.
Lines 15–17: We print the values of variables before swapping. Then, we call the swapValues
function and print the values again.
The guard
statement enhances readability and maintainability by enabling early exit if a condition is unmet. The early exit can be from a function or code block. It’s commonly used for handling preconditions at the beginning of a function, avoiding nested if
statements, and improving code clarity. Its syntax is guard condition else {}
. If the condition of the guard statement evaluates to true then the execution of the code continues as normal. However, if it evaluates to false, the code after the else
keyword is executed. It is to be noted that the else
block must contain code that transfers program control out of the scope like return
, throw
, break
, or continue
.
func test(_ name: String?) {guard let name = name else {print("guard condition is not true. Entered the else code.")return}print("guard condition was true.")}test("John")test(nil)
Lines 1–7: We defined a function test
to check the working of the guard
condition. Then we defined the guard condition that if name
is nil, the guard statement prints a message and exits the function early using return. But if name
has a value, the execution continues.
Line 9: We call the method test
with a String
value so the message on line 6 is printed.
Line 10: We call the method test
with a nil value so the guard condition becomes false, and the message on line 3 is printed.
This wraps up our blog about the top 10 Swift interview questions. We started by stating the question and explaining the answer in detail. We then provided a code-based example for better comprehension. It is to be noted that many other concepts in Swift will be covered in the next series of this blog.
To deepen your understanding of the Swift programming language, we strongly recommend you look through the following selection of specialized courses on the Educative platform:
Swift Programming for Mobile App Development
Swift is a modern and intuitive programming language that ranks among the top programming languages for mobile app development. Originally developed by Apple, Swift is now the recommended programming language for developing apps for all Apple platforms including iOS, iPadOS, macOS, tvOS, and watchOS. If you plan to write an app for an Apple device, you will need to learn to program in Swift. In this course, you will cover topics ranging from basic data types, constants and variables, arrays, dictionaries, object-oriented programming, logic and control flow, file and file system management, and error handling. On completion of this course, you will have sufficient foundational knowledge of Swift programming to begin learning other areas of Apple-based app development such as SwiftUI.
Decode the Coding Interview in Swift: Real-World Examples
Preparing for coding interviews has become a daunting task. Trying to solve enough practice questions and remember solutions can feel impossible. Fortunately, the best way to be successful in the coding interview is not to just grind through problems. The best way is to develop the skills to break down a new problem and deploy the right tools to come up with a solution. That’s why in this course, you’ll prepare for coding interviews by tackling real world problems faced by tech companies. When you solve real problems related to real projects (for example, paginating attendees in a Zoom call), not only will you have more fun preparing, but you’ll also have an easier time remembering what you’ve learned. After each project, we’ll also show you what kinds of interview problems you’ll now be able to solve using the techniques you just applied, so that your knowledge is adaptable to new problems. (This course is also available in Rust, Java, C++, C#, Go, Python, Ruby, Elixir, Scala, Kotlin and JavaScript.)
Don’t pass up this chance to increase your knowledge and expertise in Swift. Take the first step toward becoming an expert developer in Swift by immediately enrolling in Educative courses!
Free Resources