Cracking - iOS Interview - Questions Notes
Cracking - iOS Interview - Questions Notes
Constructor injection:
Property injection:
Method injection:
Testability
Flexibility
Separation of concerns:**
Reusability:
1. Hard to Mock:
6. but when write operation takes place, the barrier will behave as a
synchronous dispatch. It'll block other threads to execute
attributes: .concurrent)
private init() {}
func log(key: String, message: String, logLevel : LogLevel = .info) {
concurrentQueue.asyncAndWait(flags: .barrier, execute: {
let timestamp = DateFormatter.localizedString(from: Date(),
dateStyle: .short, timeStyle: .long)
logEvents[key] = message
print("\(timestamp) \(logLevel.rawValue) \(message)")
})
}
-Default Session: This is the most common and default session type
used in the URLSession class. A global cache, credential storage object,
and cookie storage object are used.
- Ephemeral Session:
like when you're authenticating with an API. It's also useful when you
want to keep your requests and responses private and not stored on
disk.
- Background Session:
This session type is used when you want to download or upload data in
the background, even when your app is not running.
The system handles the session and provides progress updates through
delegate methods. The background session is useful when
Data Task:
Download Task:
Upload Task:
WebSocket Task
You can implement CoW in your custom value types by using a similar
strategy. The key is to store the actual data in a reference type (like a
class) and ensure that you perform the copy operation only when a
mutation occurs.
1 Define a Reference Type for the Data: Create a class that holds the
actual data. Since classes are reference types, multiple instances can
share the same storage.
2 Use a Struct for the Public Interface: The struct will act as the value
type interface that users interact with. The struct will contain a reference
to the class that holds the data.
Example Implementation
final class CoWData {
var value: Int
init(value: Int) {
self.value = value
}
}
struct MyCoWType {
private var data: CoWData
init(value: Int) {
self.data = CoWData(value: value)
}
print(a.value) // Output: 10
print(b.value) // Output: 20
Explanation:
• Reference Type (CoWData): The CoWData class holds the actual data.
Since it’s a class, it's a reference type, and multiple MyCoWType instances
can share it.
Key Points:
• Efficient Memory Use: CoW allows multiple instances to share the same
data without unnecessary copying, reducing memory usage.
• Lazy Copying: The actual copying of data is delayed until it is absolutely
necessary, i.e., when a mutation occurs.
• Thread Safety: CoW, by design, helps avoid data races since any
mutation leads to the creation of a separate copy, isolating changes.
When to Use Custom CoW:
Custom CoW is useful when you have a value type that encapsulates data
that could be expensive to copy, and you want to ensure efficient memory
usage while maintaining value semantics. Examples include custom
collections, complex data structures, or types that interact with
performance-critical operations.
Can you explain the concept of a barrier task in GCD and its usage?
A barrier task in Grand Central Dispatch (GCD) is a special type of task
that you submit to a concurrent dispatch queue. It acts as a
synchronization point within the queue, ensuring that all tasks submitted
before the barrier task complete execution before the barrier task begins.
Similarly, tasks submitted after the barrier task will not start until the
barrier task has finished.
Barrier tasks are particularly useful when you need to perform a write
operation or any other task that should not be executed concurrently with
other tasks in a concurrent queue.
1 Execution Order: All tasks that were added to the queue before the
barrier task must complete before the barrier task is executed.
2 Exclusive Execution: While the barrier task is executing, no other tasks
in the queue will run. The barrier task has exclusive access to the queue.
3 Subsequent Tasks: Tasks added after the barrier task will only start
executing after the barrier task has completed.
Example of a Barrier Task
let concurrentQueue = DispatchQueue(label:
"com.example.concurrentQueue", attributes: .concurrent)
var sharedResource = [Int]()
// Simulate a read operation
concurrentQueue.async {
for item in sharedResource {
print("Reading item: \(item)")
}
}
workItem.notify(queue: .main) {
print("After dispatching the item, the number is \
(number).")
}
Concurrent queues:
Main queue:
```