iOS interview
How would you describe a Swift language?
It’s a type-safe language for protocol-oriented programming
Safe — fast — expressive
Swift language features
- Closures unified with function pointers
- Tuples and multiple return values
- Generics
- Fast and concise iteration over a range or collection
- Structs that support methods, extensions, and protocols
- Functional programming patterns, e.g., map and filter
- Powerful error handling built-in
- Advanced control flow with
do
,guard
,defer
, andrepeat
keywords
POP (Protocol oriented programming)
the protocol is a blueprint of methods.
protocol-oriented is an approach or programming paradigm
In Swift, value types are preferred over classes. However, object-oriented concepts don’t work well with structs and enums: a struct cannot inherit from another struct, neither can an enum inherit from another enum. So inheritance — one of the fundamental object-oriented concepts — cannot be applied to value types. On the other hand, value types can inherit from protocols, even multiple protocols. Thus, with POP, value types have become first-class citizens in Swift.
- Protocols serve as better abstractions than classes.
“Don’t start with a class, start with a protocol.” - Protocol Extensions
you can extend a protocol and provide a default implementation for methods, computed properties, subscripts, and convenience initializers. - Protocol Inheritance
A protocol can inherit from other protocols and then add further requirements on top of the requirements it inherits. - Protocol Composition
Swift does not allow multiple inheritance for classes. However, Swift types can adopt multiple protocols. Sometimes you may find this feature useful.
What’s the difference between var
and let
? Which one would you choose for properties in a struct
and why?
Let is used to declare a constant value — you won’t change it after giving it an initial value.
var is used to declare a variable value — you could change its value as you wish
This is why anything weak
can't be written using let
.
They need to change during runtime and you must be using var
instead.
structs get passed by value and not by reference, so you cannot modify the variables in a struct at all after their set. So the let keyword really makes sense.
What are lazy properties?
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.
What’s Optional
? What mechanism lays behind that? What’s unconditional unwrapping?
A type that represents either a wrapped value or nil
, the absence of a value.
This is implemented using a generic enum as follows.
The enum has two cases, to represent the absence and presence of a wrapped instance respectively. When there is no wrapped instance, the value of the optional is .none
. When the optional has a wrapped instance, its value is .some
, with the wrapped instance as the associated value. Since Optional
is a generic type, the Wrapped
type parameter is used to determine the type of the wrapped instance at the time an Optional
instance is created.
When you’re certain that an instance of Optional
contains a value, you can unconditionally unwrap the value by using the forced unwrap operator (postfix !
).Unconditionally unwrapping a nil
instance with !
triggers a runtime error.
How can we unwrap an Optional
value?What’s optional chaining, optional binding, and the nil-coalescing operator?
with 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.
In general, if the if-let
block was going to be the rest of the function, or its else
clause would have a return
or abort in it, then you should be using guard
instead. This often means (at least in my experience), when in doubt, guard
is usually the better answer. But there are plenty of situations where if let
still is appropriate.
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
.
Optional binding is a simpler and recommended way to unwrap an optional. You use optional binding to check if the optional contains a value or not. If it does contain a value, unwrap it and put it into a temporary constant or variable.
Swift’s nil coalescing operator helps you solve this problem by either unwrapping an optional if it has a value or providing a default if the optional is empty.
What’s the difference between class
and struct
?
First, let’s take a look at what classes and structs have in common:
- They can define properties to store values, and they can define functions
- They can define subscripts to provide access to values with subscript syntax
- They can define initializers to set up their initial state, with
init()
- They can be extended with
extension
(this is important!) - They can conform to protocols, for instance to support Protocol Oriented Programming
Classes support a few more capabilities that structs don’t have:
- Classes can inherit from another class, like you inherit from
UIViewController
to create your own view controller subclass - Classes can be deinitialized, i.e. you can call a function before the class is destroyed
- Classes are reference types and structs are value types
That last point is important: classes are reference types, and structs are value types. Here’s what’s what:
- Value Type: When you copy a value type (i.e., when it’s assigned, initialized or passed into a function), each instance keeps a unique copy of the data. If you change one instance, the other doesn’t change too.
- Reference Type: When you copy a reference type, each instance shares the data. The reference itself is copied, but not the data it references. When you change one, the other changes too.
class kept in memory in stack but class in a heap
What are closures?
Closures are self-contained blocks of functionality that can be passed around and used in your code.
Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.
What do weak
and unowned
mean? What’s the difference?
A reference to an instance is strong by default. But that is not always what you want. If a strong reference is not appropriate, you have a few other options, weak and unowned references.
Weak References
As the name suggests, a weak reference keeps a weak reference to the instance it references. This means that the reference to the instance is not taken into account by ARC. Remember that an instance is deallocated if no other objects have a strong reference to the instance.
Unowned References
Unowned references are similar to weak references in that they don’t keep a strong reference to the instance they are referencing. They serve the same purpose as weak references, that is, they avoid strong reference cycles.
But there are several key differences between weak and unowned references that are important to understand.
The first difference you need to know about is that an unowned reference is always expected to have a value. This is not true for weak references, which are set to nil
if the instance they reference is deallocated. When that happens, the reference is set to nil
.
Because a weak reference can be set to nil
, it is always declared as an optional. That is the second difference between weak and unowned references. The value of a weak reference needs to be unwrapped before it can be accessed whereas you can directly access the value of an unowned reference.
Be careful, though. If the referenced instance of an unowned reference is deallocated, it isn’t set to nil
. As a result, a fatal error is thrown if the referenced object of the unowned reference is accessed.
What’s an autoclosure?
The @autoclosure
attribute can be applied to a closure parameter for a function, and automatically creates a closure from an expression you pass in. When you call a function that uses this attribute, the code you write isn't a closure, but it becomes a closure, which can be a bit confusing – even the official Swift reference guide warns that overusing auto closures makes your code harder to understand.
What does the mutating
keyword mean?
The mutating keyword is only required if you are changing any state contained within the struct. Since Swift structs are immutable objects, calling a mutating function actually returns a new struct in-place (much like passing an inout parameter to a function). The mutating keyword lets callers know that the method is going to make the value change.
What do escaping and unescaping mean?
Closures are a self-contained block of functionality that can be passed around and used in your code. Closure parameters are @nonescaping by default, the closure will also be executed with the function body. If you want to escape closure, you must execution mark it as @ escaping.
Closure is like a function you can assign to a variable. You can move the variable around in your code, and call the code of the closure at a later point.
The lifecycle of @nonescaping closure,
- Pass the closure as a function argument, during the function call.
- Do some additional work with function.
- The function runs the closure.
- The function returns the compiler back.
The lifecycle of the @escaping closure:
- Pass the closure as a function argument, during the function call.
- Do some additional work in function.
- Function execute the closure asynchronously or stored.
- The function returns the compiler
Have you heard about method swizzling? What is that? Can it be done in Swift?
Method swizzling is the process of changing the implementation of an existing selector at runtime. Simply speaking, we can change the functionality of a method at runtime.
yes
What’s the difference between NSArray
and NSSet
?
The main difference is that NSArray
is for an ordered collection and NSSet
is for an unordered collection.
NSSet
- Primarily access items by comparison
- Unordered
- Does not allow duplicates
NSArray
- Can access items by index
- Ordered
- Allows duplicates
What’s KVO and KVC?
KVC stands for Key-Value Coding. It’s a mechanism by which an object’s properties can be accessed using string’s at runtime rather than having to statically know the property names at development time.
KVO stands for Key-Value Observing and allows a controller or class to observe changes to a property value.
What’s the application and controller lifecycle?
application lifecycle :
- Not Running
- In Active
- Active
- Background
- Suspended .
controller lifecycle :
init(coder:)
loadView()
viewDidLoad()
viewWillAppear(_:)
viewWillLayoutSubViews()
viewDidLayoutSubviews()
viewDidAppear(_:)
viewWillDisappear(_:)
viewDidDisappear(_:)
deinit()
What’s Core Data?
Core Data is a framework developed and maintained by Apple.
Core Data is the M in MVC, the model layer of your application.
Even though Core Data can persist data to disk
Core Data is not a database and that it manages your application’s object graph.
If you’re in need of a lightweight model layer, then Core Data shouldn’t be your first choice.
Core Data provides an abstraction that allows developers to interact with the model layer in an object-oriented manner. Every record you interact with is an object.
Core Data is responsible for the integrity of the object graph. It ensures the object graph is kept up to date.
Drawbacks
- Performance
- Multithreading
What architectures do you have experience with? What’s your favorite and why?
I used MVC , MVVN , VIPER & CleanSwift VIP
my favorite one is VIP because :
- Ready-made templates
- Unidirectional flow of data
- Testability
- Reusability
- Collaboration
What is REST? What’s a difference between the POST and GET methods?
A RESTful API is an architectural style for an application program interface (API) that uses HTTP requests to access and use data. That data can be used to GET, PUT, POST and DELETE data types, which refers to the reading, updating, creating and deleting of operations concerning resources.
GET
is used to retrieve remote data, and POST
is used to insert/update remote data
POST — The data is included in the body of the request.
GET — pass info is in the URL.
How can we handle background operations?
Operation queue
main thread , global thread
background modes like background fetch
What are the differences and similarities between a GCD and an NSOperation
?
GCD
is a low-level C-based API.NSOperation
and NSOperationQueue
are Objective-C classes.NSOperationQueue
is objective C wrapper over GCD
. If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation:
i. implementation
For GCD
implementation is very light-weightNSOperationQueue
is complex and heavy-weight
NSOperation advantages over GCD:
i. Control On Operation
you can Pause, Cancel, Resume an NSOperation
ii. Dependencies
you can set up a dependency between two NSOperations
operation will not started until all of its dependencies return true for finished.
iii. State of Operation
can monitor the state of an operation or operation queue. ready ,executing or finished
iv. Max Number of Operation
you can specify the maximum number of queued operations that can run simultaneously
When to Go for GCD
or NSOperation
when you want more control over queue (all above mentioned) use NSOperation
and for simple cases where you want less overhead (you just want to do some work "into the background" with very little additional work) use GCD
What is a dispatch queue?
A DispatchQueue
is an abstraction layer on top of the GCD queue that allows you to perform tasks asynchronously and concurrently in your application. Tasks are always executed in the order they’re added to the queue.
What is a serial queue?
A serial Dispatch Queue performs only one task at the time. Serial queues are often used to synchronize access to a specific value or resource to prevent data races to occur.
What is a concurrent queue?
A concurrent queue allows us to execute multiple tasks at the same time. Tasks will always start in the order they’re added but they can finish in a different order as they can be executed in parallel. Tasks will run on distinct threads that are managed by the dispatch queue. The number of tasks running at the same time is variable and depends on system conditions.
What’s a dispatch group?
A group of tasks that you monitor as a single unit.
Did you ever have a chance to write a custom controller transition? How can we do that?
We don’t do that often, but if we do it’s good to remember about back gestures and know how to implement them.
What’s a difference between frame
and bounds
?
The “every interview”
Constraint priorities, hugging priority, and compression resistance priority: What are those, and how do they work?
- Hugging => content does not want to grow
- Compression Resistance => content does not want to shrink
How would you store sensitive user data?
Keychain
What are generics?
Generic programming is a way to write functions and data types while making minimal assumptions about the type of data being used. Swift generics create code that does not get specific about underlying data types, allowing for elegant abstractions that produce cleaner code with fewer bugs. It allows you to write a function once and use it on different types.
Do you use any dependency manager? Which one do you prefer?
At some point you might want to use 3rd party code to get extra features or something,you can copy the source code but how you will update it in the future? keep coping it again!!
Also some of your 3rd party code might depend on other 3rd part code, and if you copied it twice, you will get duplicate symbols.
Dependency managers handle all this for you.
My advice is to use Carthage or submodules, but do not use CocoPods, anything that touches the project file is not a good practice with Apple.
Do you use Xcode’s instruments? Which ones?
Instruments is a powerful and flexible performance-analysis and testing tool that’s part of the Xcode tool set. It’s designed to help you profile your iOS, watchOS, tvOS, and macOS apps, processes, and devices in order to better understand and optimize their behavior and performance. Incorporating Instruments into your workflow from the beginning of the app development process can save you time later by helping you find issues early in the development cycle.
What is continuous integration (CI)? Do you know and use any? Have you ever configured any?
There’s plenty of them, and it’s good if you know at least one or two.
Do you have experience with unit testing? How about UI testing?
Everyone says they write tests, but do they? If you used any frameworks to help with tests, mention that as well.
What is SOLID? Can you name and describe those principles?
What is declarative programming? Have you tried SwiftUI yet?
What’s reactive programming? Do you have experience with an Rx framework and/or Apple’s Combine?