Download as pdf or txt
Download as pdf or txt
You are on page 1of 79

How do you answer an interview question?

In a way that feels clear, structured and impactful


How do you answer an interview question?

Contextualize
How do you answer an interview question?

Contextualize
Reformulate the question and state the assumptions you will
make when answering.

(This gives the interviewer the opportunity to correct you if you’re


about to go in a wrong direction!)
How do you answer an interview question?

Contextualize

Answer
How do you answer an interview question?

Answer
Give the explanation, the de nition or the best practice that
the interviewer expects to hear.

fi
How do you answer an interview question?

Contextualize

Answer

Recap
How do you answer an interview question?

Recap
Quickly sum up the key points of your answer, in one or two
sentences maximum.

And if you have more knowledge on the topic, it’s also the
moment to mention it!
How do you answer an interview question?

Contextualize

Answer

Recap
Now let’s answer some actual questions!
Question #01
What’s an Optional?
#01 – What’s an Optional?
Contextualize
One of the goals of Swift is to be a safe programing language.

Consequently, and unlike in other languages, variables cannot


by default be set to nil.

If we want a variable to be nullable, then we must explicitly


opt into this behavior, by making the type of the variable be
an Optional.
#01 – What’s an Optional?
Answer
To make a variable optional, we add a ? after its type, which
is a shortcut for the generic type Optional<T>.

By marking a variable optional, the compiler will make sure


the we explicitly deal with the potential nil value.

We can deal with this potential nil value either:


• in a safe way, using optional chaining or conditional binding
• or in an unsafe way, using force unwrapping
#01 – What’s an Optional?

Answer
Of course, in most situations we want to deal with the
Optional in a safe way.

Unsafe approaches, like force unwrapping, should be used


with a lot of caution, because a nil value will then result in a
crash.
#01 – What’s an Optional?
Recap
In short, Optional is Swift’s type-safe way of dealing with
values that can be potentially nil.

It’s interesting to note that Optional is actually implemented


in Swift itself, using a generic enum with an associated value.

(However, all the sugar syntax that makes Optional easy to


use is implemented in the compiler)
Question #02
What is the difference between an
@escaping and a non-@escaping closure?
#02 – What is the di erence between an
@escaping and a non-@escaping closure?
Contextualize
Closures are pieces of code that are de ned in one place, but
are meant to be executed at a later time.

Because they can be executed later, they need to ensure that


the values they interact with are still in memory at that time.

This ability to capture values is a double-edged sword,


because it also opens up the way to memory leaks.
ff
fi
#02 – What is the di erence between an
@escaping and a non-@escaping closure?
Answer
However, not all closures are meant to be used the same way.

Some closures are not meant to have a lifetime that exceeds


that of the function they’ve been passed to.

A typical example of such closures are the ones you pass to


functions like .map() or .filter().
ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?
Answer
We call these closures “non-escaping closures”.

Because their lifetime is limited to that of the function they are


passed to, they don’t pose a threat regarding memory safety.

This means that we don’t have to worry about capturing


strong references inside these closures.
ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?
Answer
In Swift, a closure is “non-escaping” by default.

However, some closures have the legitimate need to outlive


the function they’ve been passed to.

Think, for instance, of a network call that will complete after


that the function that started it has returned.
ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?

Answer
Such closures are called “escaping closures” and must be
annotated with @escaping.

In such closures, we must be careful when we capture a


strong reference to a reference type, because it can
potentially create a retain cycle.
ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?

Answer
However, Swift provides us with tools to capture references in
a safe manner, using the closure’s capture list.

A typical example of this is when we use [weak self].


ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?
Recap
Closures are known to be one of the top cause of memory
leaks in iOS apps.

But not all closures have the potential to create such memory
leaks.

Only closures that escape the lifetime of the function they’re


passed to can potentially be harmful.
ff
#02 – What is the di erence between an
@escaping and a non-@escaping closure?

Recap
And that’s why Swift forces us to explicitly annotate such
closures with @escaping.

Be careful however, in some instances @escaping can be


implicit, for instance when a closure argument is optional.
ff
Question #03
When would you use a computed
property vs a method?
#03 – When would you use a computed
property vs a method?
Contextualize
When we want to encapsulate a piece of code that produces
a value, we have two choices.

We can put that code either inside a computed property or


inside a method.
#03 – When would you use a computed
property vs a method?
Answer
From a technical point of view, computed properties and
methods are quite similar.

Actually, a computed property is basically a method with no


argument and a simpler syntax to call it.

Because of that, the choice between the two is more a


question of semantics.
#03 – When would you use a computed
property vs a method?

Answer
Properties are expected to have some speci c semantics:

• they shouldn’t have side e ects


• they should be idempotent (i.e. repeated calls should return
the same value)
• they should execute in constant time (i.e. O(1) complexity)
ff
fi
#03 – When would you use a computed
property vs a method?

Answer
If all these conditions are met, then it’s OK to encapsulate
that code inside a computed property.

However, if not all of them are met, then it’s better to use a
method, because the code doesn’t behave like we expect a
property to behave.
#03 – When would you use a computed
property vs a method?
Recap
Syntax sugar, like computed properties, can be really useful
to write shorter code.

But we must be careful to only use it when it actually makes


sense.

It’s usually a bad idea to use sugar syntax when 100% of the
requirement are not meant, because it leads to confusion.
Question #04
Can you explain the purpose of
the keyword guard?
#04 – Can you explain the purpose of the
keyword guard?
Contextualize
When we implement a feature, we can usually split our code
into two parts:

• the “happy path”, which implements the feature when


everything is working correctly

• the “error paths”, which deal with all the potential technical
and business errors (no network, expired token, invalid
promo code, etc.)
#04 – Can you explain the purpose of the
keyword guard?
Answer
Ideally we would like the happy path to read like the main ow
of our code, and have the error paths branch out of it.

However, if we implement our code using if statements, it’s


actually the inverse that’s happening.

Each new potential error path leads the happy path to


become more and more deeply nested.

fl
#04 – Can you explain the purpose of the
keyword guard?
Answer
It’s when the keyword guard comes into play!

guard allows us to implement an early return from a function,


when a condition has not been met.

By using guard, we can refactor our code so that it now has


a more readable structure, with the happy path at the center.
#04 – Can you explain the purpose of the
keyword guard?
Recap
guard is the typical example of how seemingly simple sugar
syntax can dramatically improve the readability of our code.

However, like with all sugar syntax, there’s always a ip side!

Here, we want to be careful when using negations inside a


guard statement, because they can be confusing to read.

fl
Question #05
Can you give an example of a bad
practice in Swift?
#05 – Can you give an example of a bad
practice in Swift?
Contextualize
Bad practices are situations where what initially felt like a
good idea actually turns out to have harmful consequences.

A typical example in Swift would be to use an advanced


language feature when it will actually do more harm than
good.
#05 – Can you give an example of a bad
practice in Swift?
Answer
Let’s take the example of the keyword defer.

defer allows us write code that will only be executed when


the current scope exits.

defer can be very useful when dealing with symmetrical


operations, like opening and closing a le.
fi
#05 – Can you give an example of a bad
practice in Swift?
Answer
Because forgetting the symmetrical call can be a dangerous
error, defer is very useful in such a context.

However, it’s worth noting that defer provides its feature by


breaking an important property.

Indeed, defer decouples the place where code written with


the time this code is executed.
#05 – Can you give an example of a bad
practice in Swift?

Answer
When we’re dealing with symmetrical calls, the upside of
using defer de nitely makes it worth it.

However, in other contexts you would de nitely want to be


careful, because defer can really make our code confusing.
fi
fi
#05 – Can you give an example of a bad
practice in Swift?
Recap
Swift o ers a lot of advanced features, so it’s not a surprise
that their indiscriminate use can turn into bad practices.

Software engineering is all about tradeo s, so whenever we


want to use a fancy trick, we should always consider both its
upside and its ip side.
ff
fl
ff
Question #06
What’s the difference between
weak and unowned?
#06 – What’s the di erence between
weak and unowned?
Contextualize
weak and unowned are two attributes that we can use to
refer to an instance without actually keep a strong reference
to it.

They are typically used in scenarios where keeping a strong


reference would result in a retain cycle, like in a closure or
with a delegate.
ff
#06 – What’s the di erence between
weak and unowned?

Answer
A weak reference is meant to be used when the other
instance has a shorter lifetime.

Because of this shorter lifetime, it’s possible for the other


instance to be deallocated by the time we use the weak
reference, and so it will be stored using an Optional.
ff
#06 – What’s the di erence between
weak and unowned?
Answer
On the other hand, an unowned reference is meant to be
used when the other instance has an equal or longer lifetime.

Because its lifetime is supposed to be equal or longer, the


other instance shouldn’t be deallocated by the time we
access the reference.

So an unowned reference will be implicitly unwrapped.


ff
#06 – What’s the di erence between
weak and unowned?
Recap
Both weak and unowned references allow us to refer to other
instances without the risk of creating a retain cycle.

However, we want to be careful with unowned references!

if our assumption that the other object will have an equal or


grater lifetime turns out to be wrong, accessing the unowned
reference will then lead to a crash.
ff
#06 – What’s the di erence between
weak and unowned?
Recap
So if you want to play it safe, it can make sense to only use
weak references in your codebase.

It’s worth noting that, because a weak reference requires


extra logic to deal with the case when the other object has
been deallocated, it is less optimized than an unowned
reference.
ff
#06 – What’s the di erence between
weak and unowned?

Recap
However, unless you write computation intensive code that
requires every possible optimization, its unlikely that you will
notice any performance issue by using only weak references.
ff
Question #07
When would you use
@autoclosure?
#07 – When would you use
@autoclosure?

Contextualize
@autoclosure in an attribute that we can apply to a closure
argument.

When that argument is applied, the expression passed as an


argument will be automatically wrapped inside a closure.
#07 – When would you use
@autoclosure?
Answer
This might seem weird at rst glance, but it actually serves an
interesting purpose!

Imagine that:
• the expression you pass is potentially expensive to
evaluate
• the function you pass it to might not always need to use it
fi
#07 – When would you use
@autoclosure?

Answer
In that situation, it could be useful to have a mechanism to
only evaluate the expression when we actually need to use it.

Wrapping the expression in a closure would achieve this goal,


but will also make the call sites a bit less readable.
#07 – When would you use
@autoclosure?
Answer
That’s when @autoclosure is useful: it automatically wraps
the argument in a closure, this way the call site can stay the
same.

A typical example of when to use @autoclosure is to


implement a logging function:
• logs are not always enabled
• the data we log can be costly to evaluate
#07 – When would you use
@autoclosure?
Recap
While @autoclosure can help optimize our code without
degrading its readability, it’s important to also keep in mind its
ip side.

It’s not obvious at the call site that the expression we pass as
an argument will not be evaluated immediately, if at all.

This can lead to subtle bugs for potential edge cases.


fl
Question #08
What open-source tools do you
recommend using and why?
#08 – What open-source tools do you
recommend using and why?
Contextualize
The iOS community has a very active open-source scene,
which produces a lot of useful tools to improve the quality of
a project.

While it’s impossible to list all the valuable tools, we can go


over the more common ones
#08 – What open-source tools do you
recommend using and why?
Answer
Swiftlint and SwiftFormat are linters that make it easier to
enforce coding rules and style across a codebase.

Fastlane is a commande-line tool to automate the shipping


process an iOS app, from code signing to app store
submission.
#08 – What open-source tools do you
recommend using and why?
Answer
SwiftGen allows to generate type safe data structures to
access the assets of an Xcode project (images, strings, etc.)

Sourcery is a code generation tool, that can be useful to


generate boilerplate code, such as mocked implementation of
protocols.
#08 – What open-source tools do you
recommend using and why?

Answer
Older projects might use CocoaPods or Carthage to deal with
dependencies. However more recent project will more like
use the Swift Package Manager instead.
#08 – What open-source tools do you
recommend using and why?
Recap
There are a lot of useful open-source tools out there that do a
great job at proving features that are not available in Xcode.

Of course the goal here is not to bloat our project by using as


many as possible, but rather to evaluate whether their are
relevant or not to our current need.
Question #09
How do you choose the minimum
version for an iOS app?
#09 – How do you choose the minimum
version for an iOS app?
Contextualize
All iOS apps must decide what is the lower version of iOS that
they support.

Because new APIs are (most of the time) not back ported to
older versions of iOS, this choice has strong technical
consequences.
#09 – How do you choose the minimum
version for an iOS app?

Answer
For instance, SwiftUI isn’t available before iOS 13. (And to be
honest, only becomes really usable with iOS 14)

The same way, Combine also isn’t available before iOS 13.
#09 – How do you choose the minimum
version for an iOS app?
Answer
Because you might not be able to use such important APIs,
the minimum version of iOS your app supports has major
consequences on your technical choices as a developer.

However, this choice cannot only be seen from the technical


point of view…
#09 – How do you choose the minimum
version for an iOS app?
Answer
As developers, we would of course like to only support the
most recent version.

This way we would get to use all the modern APIs, and we
would save a ton of time testing our app on older iOS
versions.
#09 – How do you choose the minimum
version for an iOS app?
Answer
But doing so would make our app unusable by a potential
large part of iPhone users.

So this choice also has strong business implications!

There’s no clear cut answer here, it really depends on the kind


of app you’re working on.
#09 – How do you choose the minimum
version for an iOS app?
Answer
Apps that deliver important services, like banking or the
administration will usually want to support a large number of
iOS versions.

On the other hand, apps that deliver cutting edge tech can
assume that their users update their devices more regularly
and so can a ord to support less versions.
ff
#09 – How do you choose the minimum
version for an iOS app?
Recap
Deciding on the minimum version of iOS an app will support
is de nitely not an easy choice, and is often the result of a
compromise between business and engineering.

One thing to keep in mind, if you’re about to start a new


project: make sure to choose the minimum version based on
when the app is expected to release, which could be months
or even a year away from now!
fi
Question #10
Can you explain what
Dependency Injection is?
#10 – Can you explain what Dependency
Injection is?
Contextualize
It’s a good software practice to partition our code in several
components, each tasked with ful lling a speci c
responsibility.

Of course, the question that comes immediately after is: how


do we put the pieces of the puzzle back together?
fi
fi
#10 – Can you explain what Dependency
Injection is?
Answer
Here a naive approach would be to make each component
responsible for both creating and using its dependencies.

While this works, it also strongly reduces the modularity of


our code, because it becomes impossible to swap one
component for another.
#10 – Can you explain what Dependency
Injection is?

Answer
To solve this issue, we need to decouple the creation of a
dependency with its actual use.

This process is what’s called dependency injection, and


here’s how it typically looks like.
#10 – Can you explain what Dependency
Injection is?
Answer
First, we make each dependency expose its API through a
protocol.

Then, we update the initializer of our component and we add


a new argument for each dependency, using the protocol as
the type.
#10 – Can you explain what Dependency
Injection is?
Answer
This way, the creation of the dependencies can be handled in
a separate part our code, and our component only needs to
focus on using its dependencies.

As a result, our codebase has become much more modular:


we can for instance inject mocked versions of our
dependencies when we run our tests.
#10 – Can you explain what Dependency
Injection is?
Recap
Dependency Injection is the typical example of using a $5
word to describe a ¢50 concept: it sounds super complex but
the idea behind it is actually relatively straight forward!

It’s worth noting that this way injecting dependencies is not


always possible, because it requires that you have control
over the initializer.
#10 – Can you explain what Dependency
Injection is?
Recap
We have a great example of this limitation in iOS: you might
have noticed that views de ned in a storyboard are injected
using implicitly unwrapped properties.

The reason for this choice is precisely because it wasn’t really


possible back in Objective-C to create a new initializer for
each combination of dependencies.
fi
Thank you!
If you want to keep training, here’s a list of questions:
• Can you explain what a retain cycle is?
• Di erence between overriding and overloading?
• What's the di erence between a value type and a reference type?
• Can you give a de nition of “code architecture”?
• What’s the di erence between open and public?
• How would you decode a JSON in Swift?
• Can you give an example of a best practice in Swift?
• What’s the di erence between a function and a method?
• What do you think is best between completionHandlers, Combine
and async / await?
• What are tuples and why are they useful?
• What is the di erence between self and Self?
ff
ff
ff
ff
ff
fi
If you have any feedback, just email me 📮
vincent@swiftwithvincent.com

You might also like