Interview Questions and Answers in iOS — Part 3

Interview questions and answers in iOS in very simple language.

Naveen Sharma
18 min readJun 1, 2020
Interview Questions and Answers in iOS

Q. Introduction to Swift Programming Language?
A. Swift is a general-purpose, multi-paradigm, object-oriented, functional, imperative, and block-structured programing language developed by Apple Inc. for iOS, iPadOS, macOS, watchOS, tvOS, and Linux.
It was introduced at Apple’s 2014 Worldwide Developers Conference (WWDC) with version Swift 1.0.
Swift is designed to work with Apple’s Cocoa and Cocoa Touch frameworks.
From swift 2.0 release, Swift adopted the Protocol-Oriented Programming Paradigm.

Q. What is Swift's main advantage and features?
Open sourced and easy to learn
- Fast, safe, and expressive
- Type-safe language
- Optional Types, which make applications crash-resistant
- Powerful built-in error handling
- Supports Closures, Generics
- Supports pattern matching
- Tuples for multiple return values
- Fast and concise iteration over a range or collection
- Structs that support methods, extensions, and protocols
- Functional programming patterns, e.g., map and filter
- Advanced control flow with do, guard, defer, and repeat keywords

Q. What is Notification or Broadcasting?
A. A notification is a message sent to one or more observing objects to inform them of an event in the program.

Q. How could we get the device token?
A. There are two steps to get the device token. First, we must show the user’s permission screen, after we can register for remote notifications. If these steps go well, the system will provide the device token. If we uninstall or reinstall the app, the device token would change.

Q. Explain the types of notifications?
A. There are two types of notifications: Remote(Push) and Local. Remote notification requires a connection to a server. Local notifications don’t require a server connection. Local notifications happen on the device.

Q. Local Notification?
Local Notification is introduced in iOS 4.
- Local Notification is an instance of UILocalNotification/UserNotifications.
- In iOS 10 Apple has deprecated UILocalNotification and introduced UserNotifications.
- Each application on the device is limited to 64 scheduled local notifications.
- We request authorization to send the user notifications through UNUserNotificationCenter by passing 4 options (alert, badge, sound, and car play) defined under UNAuthorizationOptions.
- We create notification through the UNNotificationRequest object which requires three pieces of information: an identifier, content, and a trigger.
- We use the UNMutableNotificationContent class to create the notification contents such as the title, subtitle, body, sound, and media attachments (if any).
- There are three basic triggers UNTimeIntervalNotificationTrigger, UNCalendarNotificationTrigger, and UNLocationNotificationTrigger.
- Notifications can also contain media attachments such as images, videos, or audio. Media attachments will appear in the long look and the short look (images).
- Actions appear as buttons in the long look of the notification. We create actions using the UNNotificationAction class.
- Custom actions must be associated with a category. We create a category using the UNNotificationCategory class. Each category can contain a set of actions to be displayed when the notification is accessed in a long look. We can reuse a category with different notifications, but each category requires a unique identifier.
- To load an image URL from the local file system and create our UNNotificationAttachment object. We then assign it to the attachments property.
- To load an image URL from the server in case of remote notification we use Notification Service Extension.
- To display a custom interface for notification we use Notification Content Extensions.

Q. What are three triggers for a Local Notification?
A. Location, Calendar, and Time Interval. A Location notification fires when the GPS on our phone is at a location or geographic region. Calendar trigger is based on calendar date broken into date components. Time Interval is a count of seconds until the timer goes off.

Q. Difference between Local and Remote Notification?
A. Remote Notification is introduced in iOS 3 and Local Notification is introduced in iOS 4.
- Local Notification is scheduled by application and delivered to the same device. Push or Remote Notifications are sent by our server to the APNS server, which pushes the notification on devices.

Q. What is Remote Notification’s payload size?
A. Remote Notification’s payload size is 4kb. If we want to send a high-quality attachment, we should use Notification Service Extension.

Q. Explain options available under UNAuthorizationOptions?
Display a number on the corner of the app’s icon.
.sound: Play a sound.
.alert: Display text.
.carPlay: Display notifications in CarPlay.
.provisional: Post non-interrupting notifications. The user won’t get a request for permission if we only use this option, but our notifications will only show silently in the Notification Center.
.providesAppNotificationSettings: Indicate that the app has its own UI for notification settings.
.criticalAlert: Ignore the mute switch and Do Not Disturb. We’ll need a special entitlement from Apple to use this option as it’s only meant to be used when absolutely necessary.

Q. Explain build in keys of “aps” dictionary of payload?
A. alert: This can be a string, or a dictionary itself. As a dictionary, it can localize the text or change other aspects of the notification.
badge: This is a number that will display in the corner of the app icon. We can remove the badge by setting this to 0.
sound: Name of a custom notification sound’s file located in the app. Custom notification sounds must be shorter than 30 seconds and have a few restrictions.
thread-id: Use this key to group notifications.
category: This defines the category of the notification, which is used to show custom actions on the notification.
content-available: By setting this key to 1, the push notification becomes silent.
mutable-content: By setting this key to 1, our app can modify the notification before displaying it.

Outside of these, we can add as much custom data as we want, as long as the payload does not exceed 4 kb.

Q. What are the biggest changes in UserNotifications?
We can add audio, video, and images (Notification Service Extension).
- We can create custom interfaces for notifications (Notification Content Extension).
- New Notification extensions allow us to manage remote notification payloads before they’re delivered.

Q. Explain the notification service extension?
A. The notification service extension lets us the chance to change the content in the notification before it is presented.

Q. Explain the notification content extension?
A. The notification content extension gives us the tools, we have in an app to design the notification.

Q. What is the difference between using notification and delegation?
Notifications and Delegates are used to accomplish nearly the same functionality. However, Delegates are one-to-one communication while Notifications are one-to-many communication at the same time.
- Notification is more like a broadcast rather than a straight communication between two objects.
- Notification removes the dependencies between the sending and receiving objects by using the notification center to manage the sending and receiving of notification.
- The other difference between notifications and delegates is that there is no possibility for the receiver of notification to return a value to the sender.

Q. Difference between Delegate and Data Source?
A. A delegate is an object that acts on behalf of, or in coordination with another object when that object encounters an event in the program. A delegate is an object that is the delegate control of the user interface for that event.
- A data source is like a delegate except that instead of being delegate control of the user interface, it is the delegate control of data.

Q. What is Protocol?
A. Protocol are interfaces which define certain methods and properties that an object respond to.
- The protocol can be adopted by a class, structure, or enumeration to provide an actual implementation of methods and properties.
- If a class adopts a Protocol, It must implement all required methods of the Protocol, it adopts.
- A class adopts more than one Protocols.
- There are two types of Protocol: Formal, Informal.

Adding Property Requirements
- A protocol can have properties as well as methods.
- A protocol declaration only specifies the required property name and type. It doesn’t say anything about whether the property should be a stored one or a computed one.
- A protocol also specifies whether each property must be gettable or gettable and settable.
- Property requirements are always declared as variable properties, prefixed with the var keyword.
- Gettable and Settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.
- A { get set } property cannot be a constant stored property. It should be a computed property and both get and set should be implemented.
- A { get } property can be any kind of property, and it is valid for the property to be also settable if required.

Adding Methods Requirements
- A protocol can have type methods or instance methods.
- Methods are declared in exactly the same way as for normal instance and type methods but without curly braces or a method body.
- Variadic parameters are allowed.
- Default values are not allowed.
- We can also add mutating instance methods to protocols. And If we mark a protocol instance method requirement as mutating, we do not need to write the mutating keyword when writing an implementation of that method for a class. The mutating keyword is only used by structures and enumerations.

Q. How to make a method inside a protocol optional in swift?
A. We can do it in two ways.
The pure — by providing the default implementation using protocol extension.
The objective — by using the @objc and optional keyword.

// Pure - Swift Way
protocol MyProtocol {
func anOptionalFunction()
func aNonOptionalFunction()
extension MyProtocol {
func anOptionalFunction() {}
// Objc Compatibility Way
@objc protocol MyProtocolObjc {
@objc optional func anOptionalFunction()
func aNonOptionalFunction()

A drawback of objc compatibility way is that MyProtocolObjc in the above example became a class only protocol. A struct cannot conform to this protocol.

Q. Mutating Methods?
A. Mutating methods are methods that we use on value types like structs and enums. These methods are allowed to modify the instance it belongs to and any properties of that instance.

Q. NSAssert in Objective C or Assert in Swift?
NSAssert/Assert is a macro that takes a condition and a message. If the condition is not met/true, then the assertion fails and NSAssert raises an exception with the message provided.
- Assert is to make sure a value is what it’s supposed to be.
- If an assertion fails that means something went wrong and so the app quits.
- One reason to use assert would be if we have some function that will not behave or will create very bad side effects if one of the parameters passed to it is not exactly some value (or a range of values) we can put an assert to make sure that value is what we expect it to be, and if it’s not then something is really wrong, and so the app quits.
- Assert can be very useful for debugging/unit testing, and also when we want frameworks to stop the users from doing “evil” things.
- It also tells us the class, method, and the line where the assertion occurred.

Asserts come in three major flavors:
1. Assertions
2. Preconditions
3. Fatal Errors

Q. What is auto-layout?
A. Auto Layout dynamically calculates the size and position of all the views in the view hierarchy, based on constraints placed on those views.

Q. Explain Generics in Swift?
A. Generic code enables us to write flexible, reusable functions, and types that can work with any type.
Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. For example, Swift’s Array and Dictionary types are both generic collections.
Generics create code that does not get specific about underlying data types. Generics allow us to know what type it is going to contain. Generics also provides optimization for our code.

Q. What is the difference between static vs class functions/variables in Swift classes?
A. Subclasses can override class methods but can not override static methods.

Q. Please explain the final keyword in the class?
A. By adding the keyword final in front of the method, property, or subscript, we prevent them from being overridden. Exp. final var, final func, final class func, and final subscript.
If we can replace the final class keyword with a single word static and get the same behavior. Any attempt to subclass a final class is reported as a compile-time error.

so, static is internally final.

class A {    
class func classFunction() { }
static func staticFunction() { }
class B: A {override class func classFunction() {}//Compile Error. Class method overrides a 'final' class method
override static func staticFunction() {}

Q. Difference between Self and self in Swift?
A. When we write protocols and protocol extensions, there’s a difference between Self (capital S) and self (lowercase S). When used with a capital S, Self refers to the type that conforms to the protocol, e.g. String or Int. When used with a lowercase S, self refers to the value inside that type, e.g. “hello Swift” or 786.

As an example, consider this extension on BinaryInteger:

extension BinaryInteger {
func squared() -> Self {
return self * self

Remember, Self with a capital S refers to whatever type is conforming to the protocol. In the example above, Int conforms to BinaryInteger, so when called on Int the method effectively reads this:

func squared() -> Int {
return self * self

On the other hand, self with a lowercase S refers to whatever value the type holds. If the example above were called on an Int storing the value 8 it would effectively be this:

func squared() -> Int {
return 8 * 8

Q. Types of properties in swift?
A. Stored Properties and Computed Properties.

Q. Explain the Stored Properties in Swift?
Stored properties store constant and variable values as part of an instance of a particular class or structure.
- Stored properties can be either variable stored properties (introduced by the var keyword) or constant stored properties (introduced by the let keyword).
- Stored properties are provided only by classes and structures.

The example below defines a structure called FixedLengthRange, which describes a range of integers whose range length cannot be changed after it is created:

struct FixedLengthRange {
var firstValue: Int
let length: Int

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
//the range represents integer values 0, 1, and 2

rangeOfThreeItems.firstValue = 6
//the range now represents integer values 6, 7, and 8

Instances of FixedLengthRange have a variable stored property called firstValue and a constant stored property called length. In the example above, length is initialized when the new range is created and cannot be changed thereafter because it is a constant property.

Q. Can enums have stored properties?
A. Enums can have methods, subscripts, and computed properties. But it cannot have stored properties.

Q. Explain the Lazy Stored Property in Swift?
A lazy stored property is a property whose initial value is not calculated until the first time it is used. We indicate a lazy stored property by writing the lazy modifier before its declaration.
- Lazy properties are useful when the initial value for a property is dependent on outside factors whose values are not known until after an instance’s initialization is complete. Lazy properties are also useful when the initial value for a property requires complex or computationally expensive setup that should not be performed unless or until it is needed.
- We must always declare a lazy property as a variable (with the var keyword) because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before the initialization completes, and therefore cannot be declared as lazy.
- If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once.
- We can’t use lazy with let.
- We can’t use it with computed properties. Because a computed property returns the value every time we try to access it after executing the code inside the computation block.
- We can use lazy only with members of struct and class.
- Lazy variables are not initialized atomically and so it is not thread-safe.

Q. Explain the Computed Properties in Swift??
A. Computed properties calculate a value rather than store it. They provide a getter and an optional setter to retrieve and set other properties and values indirectly. Computed properties are provided by classes, structures, and enumerations.
Computed properties are always variables (never constants)

var a:String?var a:String {
get {
return “a”
set(newValue) {
a = newValue

Q. What happens if we try to set a computed property in its own setter?
A. We cannot do that. It will call the same setter method again and again and it will create an endless loop. The app may crash due to a memory overrun.
By definition, a computed property is one whose value we can’t set because, well, it’s computed. It has no independent existence. The purpose of the setter in a computed property is not to set the value of the property but to set the values of other properties, from which the computed property is computed.

Q. Explain Read-Only Computed Properties?
A. A computed property with a getter but no setter is known as a read-only computed property. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value.
We can simplify the declaration of a read-only computed property by removing the get keyword and its braces:

var a:String
return “a”

Q. Property Observers?
A. Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.
We can add property observers to any stored properties we define, except for lazy stored properties. We can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass. We don’t need to define property observers for nonoverridden computed properties, because we can observe and respond to changes to their value in the computed property’s setter.
We have the option to define either or both of these observers on a property:
willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.

Q. What is the difference between property and instance variable?
A. A property is a more abstract concept. An instance variable is just a storage slot, as a slot in a struct. Normally other objects are never supposed to access them directly. Usually, a property will return or set an instance variable, but it could use data from several or none at all.

Q. Explain [weak self] and [unowned self]?
Weak and unowned are used to solve leaked memory and retain cycles.
- Both do not increase the retain count.
- If self could be nil in the closure use [weak self].
- If self will never be nil in the closure use [unowned self].
- By declaring weak we need to handle the case that it might be nil inside the closure at some point. If we try to access an unowned variable that happens to be nil, it will crash the whole program. So we only use unowned when we are positive that variable will always be around while the closure is around.
- We could use unowned when the other instance has the same lifetime or longer lifetime.
- weak will nullify the pointer whenever the reference is deallocated but unowned won’t do that, so that may result in a dangling pointer.
- Because weak references need to allow their value to be changed to nil at runtime, they are always declared as variables and optional.

According to Apple-doc:
- Weak references are always of an optional type and automatically become nil when the instance they reference is deallocated.
- If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.

Q. Can we make a let as weak?
A. No, ‘weak’ must be a mutable variable(var), because it may change at runtime. When we declare something as weak, it becomes optional. It may or may not have a value. It will be mutated [set to nil] once there is no reference to it.

class SomeClass {
weak let someObj: String? = nil
// error:
'weak' must be a mutable variable, because it may
change at runtime

Q. Why do we need to specify self to refer to a stored property or a method When writing asynchronous code?
A. Since the code is dispatched to a background thread we need to capture a reference to the correct object.

Q. Can we make a let as unowned?
A. Yes, UNOWNED references can be a let or a var. unowned references will always have a value.

Q. What is Optional Chaining in Swift?
A. 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.

Q. When do we use optional chaining vs. if let or guard?
A. We use optional chaining when we do not really care if the operation fails; otherwise, we use if let or guard. Optional chaining lets us run code only if our optional has a value.

Q. Explain Guard Statement in Swift?
A. Like if-else, the guard is a conditional statement that requires execution to exit the current block if the condition isn’t met. In simple words, A guard block only runs if the condition is false, and it will exit out of the function through the return. If the condition is true, Swift ignores the guard block. It provides an early exit and fewer brackets.
Any new optional bindings created in a guard statement’s condition are available for the rest of the function or block. It helps us to safely unwrap multiple optional values.

Q. What are the benefits of the Guard Statement?
A. There are three big benefits to guard.
One is avoiding the pyramid of doom (lots of annoying if let statements nested inside each other).
The second benefit is providing an early exit out of the function using the break or using return.
The last benefit, guard statement is another way to safely unwrap optionals.

Q. Explain Forced Unwrapping?
A. When we defined a variable as optional, then to get the value from this variable, we will have to unwrap it. This just means putting an exclamation mark at the end of the variable.
We use Forced Unwrapping when we know an optional has a value.

Q. Nil Coalescing Operators in Swift?
A. The nil-coalescing operator (a ?? b) unwraps an optional “a” if it contains a value, or returns a default value b if a is nil. The expression “a” is always of an optional type. The expression b must match the type that is stored inside a.
Note: If the value of a is non-nil, the value of b is not evaluated. This is known as short-circuit evaluation.

Q. What is Downcasting?
A. When we cast an object to another type in Objective-C, it’s pretty simple since there’s only one way to do it. In Swift, though, there are two ways to cast — one that’s safe and one that’s not.
as used for upcasting and type casting to bridged type
as? used for safe casting, return nil if failed
as! used to force casting, crash if failed. should only be used when we know the downcast will succeed.

Q. Explain the Defer Statement in Swift?
A. Defer Statement: Put off (an action or event) to a later time; postpone.
A defer block executes only after the current scope (loop, method, etc) exits.

func simpleDefer() {
defer { print("Chill, later") }
print("Print First")

Let us execute the simpleDefer() function.
// “Print First”
// “Chill, later”

Q. What is Tuple in Swift?
A. Tuple (Functions with Multiple Return Values)- Tuple is a group of different values represented as one. According to apple, a tuple type is a comma-separated list of zero or more types, enclosed in parentheses.
() is the empty tuple — it has no elements. It also represents the Void type.
Tuples don’t conform to the hashable protocol. Hence it cannot be used as dictionary keys.
Tuple is a value type. When we initialize a variable tuple with another one it will actually create a copy.
Please note that tuples are passed by value, not reference.

Q. Optional Tuple in Swift?
A. If the tuple type to be returned from a function has the potential to have “no value” for the entire tuple, we can use an optional tuple return type to reflect the fact that the entire tuple can be nil. We write an optional tuple return type by placing a question mark after the tuple type’s closing parenthesis, such as (Int, Int)? or (String, Int, Bool)?.
Note: An optional tuple type such as (Int, Int)? is different from a tuple that contains optional types such as (Int?, Int?). With an optional tuple type, the entire tuple is optional, not just each individual value within the tuple.

Q. In-Out Parameter in Swift?
A. Function parameters are constants by default. in-out means that modifying the local variable will also modify the passed-in parameters. Without it, the passed-in parameters will remain the same value.
In another word, If we want a function to modify a parameter’s value, and we want those changes to persist after the function call has ended, we define that parameter as an in-out parameter instead.
In-out parameters cannot have default values, and variadic parameters cannot be marked as in-out.
func swapTwoInts(_ a: inout Int, _ b: inout Int) {}

Q. How is an in-out parameter different from a regular parameter?
A. An In-out passes by reference while a regular parameter passes by value.

Thank you for reading! If you liked this article, please clap to get this article seen by more people.
Please follow me on Medium by clicking Follow.
I’m also active on LinkedIn, Twitter, and GitHub.