InterviewPitch
Swift interview questions

Swift Interview Questions with Answers

Most Asked Swift Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

Swift is a powerful and intuitive programming language developed by Apple for building apps for iOS, macOS, watchOS, and tvOS. Designed to be safe, fast, and expressive, Swift combines the performance of compiled languages with the simplicity and interactivity of modern scripting languages. This comprehensive guide presents 100+ carefully curated Swift interview questions and answers, covering everything from the fundamentals to advanced topics. You'll master variables, data types, optionals, control flow, functions, closures, structs, classes, protocols, generics, error handling, concurrency (async/await, actors, DispatchQueue), extensions, property wrappers, and real-world iOS development patterns. Whether you're preparing for an iOS developer role, a macOS engineer position, or a Swift backend job (Vapor), this question bank will solidify your understanding and give you the confidence to ace your interview. Start practicing now and become a Swift expert.

Why Swift?

  • Modern, safe, and fast – designed for Apple's ecosystem and beyond
  • Strong type system with optionals for null safety
  • Excellent tooling with Xcode and Swift Package Manager
  • Used for iOS, macOS, watchOS, tvOS, and server-side (Vapor)
  • Growing community and high demand in the job market
  • Open source with continuous innovation from Apple and the community

Most Asked Swift Interview Questions

Beginner
1. What is Swift?

Swift is a powerful and intuitive programming language developed by Apple for iOS, macOS, watchOS, and tvOS app development.

  • Safe: Designed for safety with optionals and type safety
  • Fast: Compiled to native code for high performance
  • Expressive: Clean syntax with modern features
  • Interoperable: Works with Objective-C and C
  • Open source: Available for multiple platforms
swift
// Hello World in Swift
import Foundation

print("Hello, World!")

// Using function
func greet() {
    print("Hello, World!")
}
greet()
Beginner
2. How to declare variables in Swift?

Variables in Swift are declared with var (mutable) and let (immutable). Type inference is supported.

  • let: Immutable constant
  • var: Mutable variable
  • Type inference: Types can be omitted
  • Explicit types: let name: String = "Alice"
  • Optionals: Type? for nullable values
swift
// Variables in Swift
// Immutable variable (let - constant)
let immutableVar = "World"

// Mutable variable (var)
var mutableVar = "Hello"
mutableVar = "Swift"

// Type inference
var inferred = 42

// Explicit type annotation
var explicit: Int = 10

// Constants
let pi: Double = 3.14159

// Display
print(immutableVar)
print(mutableVar)
print(inferred)
print(explicit)
print(pi)

// Optional variable (can be nil)
var optionalVar: String? = "Optional"

// Multiple declarations
var (a, b) = (1, 2)
Beginner
3. What are the data types in Swift?

Swift has a rich type system with both primitive and complex types, including optionals for null safety.

  • Integers: Int, UInt, Int8, Int16, Int32, Int64
  • Floating point: Float, Double
  • Boolean: Bool
  • Character: Character
  • String: String
  • Array: [Type]
  • Dictionary: [Key: Value]
  • Tuple: (Type1, Type2)
  • Optional: Type?
swift
// Data Types in Swift
// Integer types
let intNum: Int = 10
let unsigned: UInt = 100
let int8: Int8 = 127
let int64: Int64 = 1000000

// Floating point
let floatNum: Float = 3.14
let doubleNum: Double = 3.14159

// Boolean
let isActive: Bool = true
let isInactive: Bool = false

// Character
let charVal: Character = "A"

// String
let strVal: String = "Hello Swift"

// Array
let arr: [Int] = [1, 2, 3, 4, 5]

// Tuple
let tuple: (Int, Double, String) = (10, 3.14, "hello")

// Dictionary
let dict: [String: Int] = ["one": 1, "two": 2]

// Optional
var optional: Int? = nil

// Type checking
print(type(of: intNum))
Beginner
4. How to define functions in Swift?

Functions in Swift are defined with the func keyword. They support parameters, return values, and closures.

  • Basic: func name(parameters) -> ReturnType { }
  • Default parameters: func greet(name: String = "Guest")
  • Multiple returns: func divide() -> (Int, Int)
  • Variadic parameters: func sum(_ numbers: Int...)
  • Closures: { (params) -> ReturnType in }
swift
// Functions in Swift
// Basic function
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

// Function with multiple return values (tuple)
func divide(_ a: Int, _ b: Int) -> (quotient: Int, remainder: Int) {
    return (a / b, a % b)
}

// Function with default parameters
func greet(_ name: String = "Guest") -> String {
    return "Hello, \(name)!"
}

// Function with variadic parameters
func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}

// Higher-order function
func operate(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

// Closure (lambda)
let multiply = { (a: Int, b: Int) -> Int in
    return a * b
}

// Usage
print(add(5, 3))
let result = divide(10, 3)
print("Quotient: \(result.quotient), Remainder: \(result.remainder)")
print(greet("Alice"))
print(sum(1, 2, 3, 4, 5))
print(operate(6, 7, operation: multiply))
Beginner
5. What are arrays in Swift?

Arrays are ordered collections of elements of the same type. They can be mutable or immutable.

  • Creation: let numbers = [1, 2, 3]
  • Access: numbers[0]
  • Modification: numbers.append(4)
  • Methods: map, filter, reduce
  • Type safety: Homogeneous types
swift
// Arrays in Swift
// Array creation
var numbers: [Int] = [1, 2, 3, 4, 5]
var strings: [String] = ["Apple", "Banana", "Orange"]
var mixed: [Any] = [1, "Hello", 3.14]

// Access and modify
print(numbers[2])  // Access element
numbers[2] = 10    // Modify element

// Array operations
print(numbers.count)
numbers.append(6)   // Add element
numbers.removeLast() // Remove last element

// Iteration
for num in numbers {
    print(num)
}

// Array methods
let doubled = numbers.map { $0 * 2 }
let filtered = numbers.filter { $0 > 2 }
let sum = numbers.reduce(0, +)

// Display
print(doubled)
print(filtered)
print(sum)

// Array with type annotation
var emptyArray: [Int] = []
var anotherEmpty = [Int]()
Beginner
6. What are collections in Swift?

Swift collections include Array, Set, and Dictionary, each with immutable and mutable variants.

  • Array: Ordered collection with duplicates
  • Set: Unordered collection without duplicates
  • Dictionary: Key-value pairs
  • Immutability: let for immutable
  • Operations: filter, map, reduce
swift
// Collections in Swift
// Array (ordered, allows duplicates)
let immutableArray = [1, 2, 3, 4, 5]
var mutableArray = [1, 2, 3]
mutableArray.append(4)
mutableArray.remove(at: 1)

// Set (unordered, unique values)
let immutableSet: Set = [1, 2, 3]
var mutableSet: Set = [1, 2, 3]
mutableSet.insert(4)
mutableSet.remove(2)

// Dictionary (key-value pairs)
let immutableDict: [String: String] = ["key1": "value1", "key2": "value2"]
var mutableDict: [String: String] = ["key1": "value1"]
mutableDict["key2"] = "value2"
mutableDict.removeValue(forKey: "key1")

// Collection operations
let numbers = [1, 2, 3, 4, 5, 6]
let evens = numbers.filter { $0 % 2 == 0 }
let doubled = numbers.map { $0 * 2 }
let sum = numbers.reduce(0, +)

print(evens)
print(doubled)
print(sum)
Beginner
7. What are structs in Swift?

Structs are value types that encapsulate data and behavior. They are the preferred data model in Swift.

  • Definition: struct Person { var name: String }
  • Value type: Copied when assigned
  • Methods: func greet()
  • Mutating: mutating func for modifications
  • Memberwise initializer: Automatic initializer
swift
// Structs (Data Classes) in Swift
struct Person {
    var name: String
    var age: Int
    var city: String
    
    // Initializer (provided automatically)
    // Memberwise initializer: Person(name:age:city:)
    
    // Method
    func greet() -> String {
        return "Hello, my name is \(name)"
    }
    
    // Mutating method
    mutating func incrementAge() {
        age += 1
    }
}

// Struct with default values
struct User {
    var name: String
    var age: Int = 0
    var city: String = "Unknown"
}

// Usage
var person1 = Person(name: "Alice", age: 25, city: "NYC")
let person2 = person1 // Copy (structs are value types)

// Update using struct update syntax
var person3 = person1
person3.age = 26

print(person1.name)
print(person1.age)
print(person1.city)
print(person1.greet())

// User with default
let user = User(name: "Bob")
print(user.city)
Beginner
8. What are enums in Swift?

Enums define a set of related values. They can have associated values and raw values.

  • Definition: enum Status { case active, inactive }
  • Associated values: case success(String)
  • Raw values: enum Status: Int { case active = 1 }
  • Methods: Can have computed properties and methods
  • Pattern matching: switch statements
swift
// Enums (Sealed Classes) in Swift
enum Result<T, E: Error> {
    case success(T)
    case failure(E)
}

enum Shape {
    case circle(radius: Double)
    case rectangle(width: Double, height: Double)
    case point
}

extension Shape {
    func area() -> Double {
        switch self {
        case .circle(let radius):
            return Double.pi * radius * radius
        case .rectangle(let width, let height):
            return width * height
        case .point:
            return 0
        }
    }
}

// Enum with associated values
enum Payment {
    case cash(amount: Double)
    case creditCard(number: String, expiry: String)
    case paypal(email: String)
}

func handlePayment(_ payment: Payment) -> String {
    switch payment {
    case .cash(let amount):
        return "Cash amount: $\(amount)"
    case .creditCard(let number, let expiry):
        return "Card: \(number), Expiry: \(expiry)"
    case .paypal(let email):
        return "PayPal: \(email)"
    }
}

// Enum with raw values
enum Status: Int {
    case success = 200
    case error = 500
    case loading = 100
}

enum Color: String {
    case red = "RED"
    case green = "GREEN"
    case blue = "BLUE"
}

// Usage
let result = Result.success("Data loaded")
let shape = Shape.circle(radius: 5.0)
let payment = Payment.creditCard(number: "1234-5678", expiry: "12/25")

print(shape.area())
print(handlePayment(payment))
print(Status.success.rawValue)
print(Color.red.rawValue)
Beginner
9. What is null safety in Swift?

Swift uses optionals for null safety, requiring explicit handling of nil values.

  • Optionals: Type?
  • Optional binding: if let
  • Guard statements: guard let
  • Nil coalescing: ??
  • Optional chaining: ?
swift
// Null Safety in Swift (Optionals)
func main() {
    // Optional types
    var nullableString: String? = "Hello"
    var nullString: String? = nil
    
    // Safe access with optional binding
    if let str = nullableString {
        print("String is: \(str)")
        print("Length: \(str.count)")
    }
    
    // Guard statement
    guard let str = nullableString else {
        print("String is nil")
        return
    }
    print("Guard: \(str)")
    
    // Nil-coalescing operator (Elvis operator)
    let value = nullString ?? "default"
    print("Value: \(value)")
    
    // Optional chaining
    let length = nullableString?.count ?? 0
    print("Length: \(length)")
    
    // Force unwrap (use carefully!)
    let forced = nullableString!
    print("Forced: \(forced)")
    
    // Map and flatMap
    let upper = nullableString.map { $0.uppercased() }
    print("Upper: \(upper ?? "nil")")
    
    // Optional pattern matching
    if case .some(let str) = nullableString {
        print("Pattern matched: \(str)")
    }
}

main()
Beginner
10. What are control flow statements in Swift?

Swift provides if-else, switch, for-in, while, and repeat-while loops for control flow.

  • If-else: if condition { } else { }
  • Switch: switch value { case pattern: }
  • For-in: for item in collection { }
  • While: while condition { }
  • Repeat-while: repeat { } while condition
swift
// Control Flow in Swift
// If-else
let age = 25
let status = age < 18 ? "Minor" : "Adult"
print(status)

// If-else-if
let grade = "A"
var result: String
if grade == "A" {
    result = "Excellent"
} else if grade == "B" {
    result = "Good"
} else if grade == "C" {
    result = "Fair"
} else {
    result = "Needs Improvement"
}
print(result)

// Switch statement
let score = 85
switch score {
case 90...100:
    print("A")
case 80..<90:
    print("B")
case 70..<80:
    print("C")
default:
    print("F")
}

// For-in loop
for i in 0..<5 {
    print(i)
}

// For-in with step
for i in stride(from: 1, through: 10, by: 2) {
    print(i)
}

// For-in descending
for i in (0..<10).reversed() {
    print(i)
}

// While loop
var i = 0
while i < 5 {
    print(i)
    i += 1
}

// Repeat-while (do-while)
i = 0
repeat {
    print(i)
    i -= 1
} while i > 0

// For-in with where clause
for i in 1...10 where i % 2 == 0 {
    print("Even: \(i)")
}
Beginner
11. What are classes and inheritance in Swift?

Swift supports classes with single inheritance, protocols for interfaces, and method overriding.

  • Class definition: class Animal
  • Inheritance: class Dog: Animal
  • Override: override func
  • Protocols: protocol Flyable
  • Reference types: Shared instance
swift
// Classes and Inheritance in Swift
// Base class
class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func makeSound() -> String {
        return "Animal sound"
    }
}

// Derived class
class Dog: Animal {
    var breed: String
    
    init(name: String, breed: String) {
        self.breed = breed
        super.init(name: name)
    }
    
    override func makeSound() -> String {
        return "Woof!"
    }
}

// Abstract class (using protocol)
protocol Vehicle {
    func start() -> String
}

extension Vehicle {
    func stop() -> String {
        return "Stopped"
    }
}

// Car implementing protocol
class Car: Vehicle {
    func start() -> String {
        return "Car started"
    }
}

// Multiple protocols
protocol Flyable {
    func fly() -> String
}

protocol Swimmable {
    func swim() -> String
}

class Duck: Flyable, Swimmable {
    func fly() -> String {
        return "Flying"
    }
    
    func swim() -> String {
        return "Swimming"
    }
}

// Usage
let dog = Dog(name: "Rex", breed: "German Shepherd")
print(dog.makeSound())
print(dog.name)
print(dog.breed)

let duck = Duck()
print(duck.fly())
print(duck.swim())
Beginner
12. What are properties in Swift?

Properties in Swift include stored, computed, lazy, and observed properties with property wrappers.

  • Stored: var name: String
  • Computed: var fullName: String { return name }
  • Lazy: lazy var data = { }()
  • Observers: didSet, willSet
  • Property wrappers: @State, @Binding
swift
// Properties in Swift
class Person {
    // Stored properties
    var name: String
    var age: Int
    
    // Computed property
    var fullName: String {
        return "\(name) (Age: \(age))"
    }
    
    // Lazy property
    lazy var expensiveData: String = {
        print("Computing expensive data...")
        return "Expensive Result"
    }()
    
    // Property observer
    var email: String {
        didSet {
            print("Email changed from \(oldValue) to \(email)")
        }
    }
    
    // Read-only computed property
    var isAdult: Bool {
        return age >= 18
    }
    
    // Init with validation
    init(name: String, age: Int, email: String) {
        self.name = name
        self.age = age
        self.email = email
    }
    
    // Setter with validation
    func setAge(_ newAge: Int) {
        if newAge >= 0 {
            age = newAge
        }
    }
}

// Struct with property wrapper
@propertyWrapper
struct Trimmed {
    private var value: String = ""
    
    var wrappedValue: String {
        get { value }
        set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }
    
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

struct User {
    @Trimmed var name: String
}

// Usage
let person = Person(name: "Alice", age: 25, email: "alice@example.com")
print(person.fullName)
print(person.expensiveData)
print(person.isAdult)

var user = User(name: "  Alice  ")
print(user.name) // "Alice" (trimmed)
Intermediate
13. What are class methods and static methods?

Class methods are defined with static or class keywords. Static methods cannot be overridden.

  • Static: static func method()
  • Class: class func method()
  • Singleton pattern: static let shared = Class()
  • Factory methods: Create instances
  • Type properties: static var
swift
// Class Methods and Static Methods
class MyClass {
    // Class variable (static)
    static var counter = 0
    static let tag = "MyClass"
    
    // Static method
    static func classMethod() {
        print("Class method called, counter: \(counter)")
    }
    
    // Factory method
    static func create() -> MyClass {
        counter += 1
        return MyClass()
    }
    
    // Instance method
    func instanceMethod() {
        print("Instance method called")
    }
}

// Class with singleton
class Singleton {
    static let shared = Singleton()
    
    private init() {} // Private initializer
    
    var data: [String] = []
    
    func addData(_ item: String) {
        data.append(item)
    }
}

// Usage
print(MyClass.tag)
let obj1 = MyClass.create()
let obj2 = MyClass.create()
MyClass.classMethod()

let singleton1 = Singleton.shared
let singleton2 = Singleton.shared
singleton1.addData("Hello")
print(singleton2.data) // ["Hello"]
Intermediate
14. How to handle exceptions in Swift?

Swift uses throws, do-catch, try?, and try! for error handling.

  • Throws: func method() throws
  • Do-catch: do { try } catch { }
  • Try?: Returns optional try?
  • Try!: Force unwrap try!
  • Defer: Cleanup code
swift
// Exception Handling in Swift
// Custom error
enum AgeError: Error {
    case invalidAge(age: Int)
    case negativeAge
}

// Function that throws
func validateAge(_ age: Int) throws {
    if age < 0 {
        throw AgeError.negativeAge
    }
    if age > 150 {
        throw AgeError.invalidAge(age: age)
    }
}

// Function with try
func divide(_ a: Int, _ b: Int) throws -> Int {
    guard b != 0 else {
        throw NSError(domain: "DivideError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Division by zero"])
    }
    return a / b
}

// Usage
func main() {
    // do-catch
    do {
        try validateAge(25)
        print("Age is valid")
    } catch AgeError.negativeAge {
        print("Age cannot be negative")
    } catch AgeError.invalidAge(let age) {
        print("Invalid age: \(age)")
    } catch {
        print("Unknown error: \(error)")
    }
    
    // try? (returns nil on error)
    let result = try? divide(10, 2)
    print("Result: \(result ?? 0)")
    
    // try! (force, crashes on error)
    // let forced = try! divide(10, 2)
    
    // defer (finally equivalent)
    func readFile() {
        defer {
            print("Closing resources...")
        }
        print("Reading file...")
    }
    readFile()
    
    // Result type
    let result2 = Result { try divide(10, 2) }
    switch result2 {
    case .success(let value):
        print("Success: \(value)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

main()
Intermediate
15. What are closures in Swift?

Closures are self-contained blocks of functionality that can be passed around and used in code.

  • Syntax: { (params) -> ReturnType in }
  • Shorthand: { $0 + $1 }
  • Trailing closures: func() { }
  • Capturing values: Captures variables
  • Escaping: @escaping for stored closures
swift
// Closures in Swift
// Basic closure
let square = { (x: Int) -> Int in
    return x * x
}

// Closure with multiple parameters
let add = { (a: Int, b: Int) -> Int in
    return a + b
}

// Closure with multiple lines
let complexOperation = { (x: Int) -> Int in
    let y = x * 2
    return y + 10
}

// Higher-order function
func operate(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

// Closure capturing environment
func makeMultiplier(_ factor: Int) -> (Int) -> Int {
    return { x in
        return x * factor
    }
}

// Trailing closure
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
let filtered = numbers.filter { $0 > 2 }

// Closure with shorthand argument names
let sum = numbers.reduce(0) { $0 + $1 }

// Escaping closure
var completionHandlers: [() -> Void] = []
func addCompletionHandler(handler: @escaping () -> Void) {
    completionHandlers.append(handler)
}

// Usage
print(square(5))
print(add(5, 3))
print(complexOperation(5))
print(operate(6, 7) { $0 * $1 })

let double = makeMultiplier(2)
print(double(5))

print(doubled)
print(filtered)
Intermediate
16. What are scope functions in Swift?

Swift doesn't have built-in scope functions like Kotlin, but similar patterns can be implemented with closures.

  • with: Custom with function
  • also: Custom also function
  • let: Using closures
  • takeIf: Custom function
  • Closures: For scoping
swift
// Scope Functions in Swift
// Swift doesn't have built-in scope functions like Kotlin
// But we can use closures and with/run patterns

struct Person {
    var name: String
    var age: Int
    var city: String
}

// let - execute block (using closure)
func processPerson() {
    var person = Person(name: "Alice", age: 25, city: "NYC")
    
    let result = { () -> Person in
        print("Name: \(person.name)")
        person.age += 1
        return person
    }()
    print("Updated age: \(result.age)")
}

// apply - configure object (using with)
func with<T, R>(_ obj: T, _ block: (inout T) -> R) -> R {
    var mutable = obj
    return block(&mutable)
}

let updated = with(Person(name: "Alice", age: 25, city: "NYC")) { person in
    person.age = 26
    person.city = "SF"
}

print(updated)

// also - perform additional operations
func also<T>(_ obj: T, _ block: (T) -> Void) -> T {
    block(obj)
    return obj
}

let person = also(Person(name: "Alice", age: 25, city: "NYC")) { p in
    print("Before: \(p)")
}

// take-if equivalent
func takeIf<T>(_ value: T, predicate: (T) -> Bool) -> T? {
    return predicate(value) ? value : nil
}

let adult = takeIf(25) { $0 >= 18 }
print(adult ?? 0)
Intermediate
17. What are extension functions in Swift?

Extensions in Swift add new functionality to existing types without subclassing.

  • Extension: extension String { }
  • Computed properties: var property: Type { }
  • Methods: Add instance and class methods
  • Protocol extensions: extension Collection { }
  • Default implementations: Provide default behavior
swift
// Extension Functions in Swift
// String extensions
extension String {
    func isEmail() -> Bool {
        return contains("@") && contains(".")
    }
    
    func addPrefix(_ prefix: String) -> String {
        return prefix + self
    }
    
    func wordCount() -> Int {
        return components(separatedBy: .whitespacesAndNewlines)
            .filter { !$0.isEmpty }
            .count
    }
}

// Numeric extensions
extension Int {
    func isEven() -> Bool {
        return self % 2 == 0
    }
    
    func isOdd() -> Bool {
        return self % 2 != 0
    }
}

// Array extensions
extension Array {
    func secondOrNil() -> Element? {
        return count >= 2 ? self[1] : nil
    }
}

// Usage
let email = "test@example.com"
print(email.isEmail())

let greeting = "Hello".addPrefix("Greeting: ")
print(greeting)

print(5.isEven())
print("Hello World".wordCount())

let numbers = [1, 2, 3]
print(numbers.secondOrNil() ?? "nil")

// Protocol extension
extension Collection {
    func isNotEmpty() -> Bool {
        return !isEmpty
    }
}

print([1, 2, 3].isNotEmpty())
Intermediate
18. What are type aliases in Swift?

Type aliases provide alternative names for existing types, improving readability and reusability.

  • Definition: typealias Name = OriginalType
  • Function types: typealias Operation = (Int, Int) -> Int
  • Complex types: typealias UserMap = [String: User]
  • Tuple types: typealias Pair = (String, Int)
  • Generic types: typealias Result<T> = (T) -> Void
swift
// Type Aliases in Swift
// Type aliases for complex types
typealias Operation = (Int, Int) -> Int
typealias UserMap = [String: User]
typealias UserId = Int
typealias UserName = String
typealias ResultCallback = (Result<String, Error>) -> Void

// Using type aliases
struct User {
    let id: UserId
    let name: UserName
}

func execute(_ op: Operation, _ a: Int, _ b: Int) -> Int {
    return op(a, b)
}

// Function type alias
typealias OperationFn = (Int, Int) -> Int

func add(_ a: Int, _ b: Int) -> Int { return a + b }
func multiply(_ a: Int, _ b: Int) -> Int { return a * b }

// Tuple type alias
typealias UserInfo = (name: String, age: Int)

// Usage
let addOp: Operation = { $0 + $1 }
let multiplyOp: Operation = { $0 * $1 }

print(execute(addOp, 5, 3))
print(execute(multiplyOp, 5, 3))

let addFn: OperationFn = add
let multiplyFn: OperationFn = multiply

print(addFn(5, 3))
print(multiplyFn(5, 3))

var users: UserMap = [:]
users[1] = User(id: 1, name: "Alice")
users[2] = User(id: 2, name: "Bob")

if let user = users[1] {
    print("User: \(user.name)")
}

let userInfo: UserInfo = (name: "Alice", age: 25)
print("Name: \(userInfo.name), Age: \(userInfo.age)")
Intermediate
19. What are inline functions in Swift?

Swift uses @inline attributes for performance optimization, though the compiler handles most inlining.

  • @inline(__always): Force inline
  • @inline(never): Prevent inline
  • Generic functions: Often inlined
  • Performance: Reduces function call overhead
  • Compiler optimization: Automatic inlining
swift
// Inline Functions in Swift
// Swift uses @inline attribute for performance optimization

// Inline function
@inline(__always)
func square(_ x: Int) -> Int {
    return x * x
}

// Inline always
@inline(__always)
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

// Inline never
@inline(never)
func complexCalculation(_ x: Int) -> Int {
    let y = x * 2
    return y + 10
}

// Generic inline function
@inline(__always)
func process<T>(_ value: T, transform: (T) -> T) -> T {
    return transform(value)
}

// Measurement macro (compile-time)
func measureTime(_ block: () -> Void) {
    let start = CFAbsoluteTimeGetCurrent()
    block()
    let end = CFAbsoluteTimeGetCurrent()
    print("Time: \(end - start)s")
}

// Usage
print(square(5))
print(add(5, 3))
print(complexCalculation(5))

let result = process(5) { $0 * 2 }
print(result)

measureTime {
    Thread.sleep(forTimeInterval: 0.1)
    print("Operation completed")
}
Intermediate
20. What are higher-order functions in Swift?

Higher-order functions take functions as parameters or return functions. Swift supports them natively.

  • Function parameters: func operate(_ operation: (Int, Int) -> Int)
  • Returning functions: func getMultiplier() -> (Int) -> Int
  • Map, filter, reduce: Built-in HOFs
  • Composition: Combine functions
  • Closures: First-class citizens
swift
// Higher-Order Functions in Swift
// Function that takes a function as parameter
func applyOperation(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

// Function that returns a function
func getMultiplier(_ factor: Int) -> (Int) -> Int {
    return { x in
        return x * factor
    }
}

// Function composition
func compose<T, U, V>(_ f: @escaping (U) -> V, _ g: @escaping (T) -> U) -> (T) -> V {
    return { x in
        return f(g(x))
    }
}

// Higher-order function with multiple closures
func process(_ value: Int, transform: (Int) -> Int, filter: (Int) -> Bool) -> Int? {
    return filter(value) ? transform(value) : nil
}

// Usage
let result = applyOperation(10, 20) { $0 + $1 }
print(result)

let double = getMultiplier(2)
print(double(5))

let square = { (x: Int) -> Int in x * x }
let addTen = { (x: Int) -> Int in x + 10 }
let squareThenAddTen = compose(addTen, square)
print(squareThenAddTen(5))

let processed = process(5, transform: { $0 * 2 }, filter: { $0 > 3 })
print(processed ?? 0)

// Built-in higher-order functions
let numbers = [1, 2, 3, 4, 5]
let squared = numbers.map { $0 * $0 }
let even = numbers.filter { $0 % 2 == 0 }
let sum = numbers.reduce(0, +)

print(squared)
print(even)
print(sum)
Advanced
21. What is async/await in Swift?

Async/await in Swift provides structured concurrency for asynchronous programming, available from Swift 5.5.

  • async: func fetch() async -> String
  • await: let result = await fetch()
  • Task: Task { }
  • Async sequences: AsyncStream
  • Task groups: withTaskGroup
swift
// Async/Await in Swift
import Foundation

// Basic async function
func fetchData() async -> String {
    try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
    return "Data loaded"
}

// Async function with timeout
func fetchWithTimeout() async throws -> String {
    let timeout = Task {
        try await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds
        return "Timeout"
    }
    
    let data = Task {
        try await fetchData()
    }
    
    let result = await withTaskGroup(of: String.self) { group in
        group.addTask { await timeout.result ?? "" }
        group.addTask { await data.result ?? "" }
        var firstResult = ""
        for await value in group {
            firstResult = value
            group.cancelAll()
            break
        }
        return firstResult
    }
    
    return result
}

// Multiple async tasks
func parallelTasks() async -> [String] {
    async let task1 = fetchData()
    async let task2 = fetchData()
    async let task3 = fetchData()
    
    let results = await [task1, task2, task3]
    return results
}

// Async with timeout and error handling
func asyncWithTimeout() async {
    do {
        let result = try await withTimeout(seconds: 0.5) {
            try await fetchData()
        }
        print("Result: \(result)")
    } catch {
        print("Timeout or error: \(error)")
    }
}

func withTimeout<T>(seconds: Double, operation: @escaping () async throws -> T) async throws -> T {
    try await withThrowingTaskGroup(of: T.self) { group in
        group.addTask {
            try await operation()
        }
        group.addTask {
            try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
            throw NSError(domain: "Timeout", code: 1, userInfo: nil)
        }
        let result = try await group.next()!
        group.cancelAll()
        return result
    }
}

// Async sequence (stream)
func asyncStream() -> AsyncStream<String> {
    return AsyncStream { continuation in
        Task {
            for i in 1...5 {
                try? await Task.sleep(nanoseconds: 100_000_000)
                continuation.yield("Item \(i)")
            }
            continuation.finish()
        }
    }
}

// Usage
Task {
    let data = await fetchData()
    print(data)
    
    let results = await parallelTasks()
    print("Results: \(results)")
    
    await asyncWithTimeout()
    
    for await item in asyncStream() {
        print(item)
    }
}
Advanced
22. What are iterators and sequences?

Iterators provide sequential access to elements, and sequences define the iteration protocol.

  • IteratorProtocol: mutating func next() -> Element?
  • Sequence: func makeIterator() -> Iterator
  • Lazy sequences: .lazy
  • Infinite sequences: Can be infinite
  • Sequence adapters: map, filter, drop
swift
// Iterators and Sequences in Swift
// Basic iterator
let numbers = [1, 2, 3, 4, 5]

// Map, filter, reduce
let doubled = numbers.map { $0 * 2 }
let evens = numbers.filter { $0 % 2 == 0 }
let sum = numbers.reduce(0, +)

print("Doubled: \(doubled)")
print("Evens: \(evens)")
print("Sum: \(sum)")

// Custom iterator
struct Counter: Sequence {
    let max: Int
    
    func makeIterator() -> CounterIterator {
        return CounterIterator(max: max)
    }
}

struct CounterIterator: IteratorProtocol {
    var current = 0
    let max: Int
    
    mutating func next() -> Int? {
        current += 1
        return current <= max ? current : nil
    }
}

let counter = Counter(max: 10)
for num in counter {
    print(num)
}

// Lazy sequences
let lazySequence = (1...10).lazy
    .map { x -> Int in
        print("Mapping: \(x)")
        return x * 2
    }
    .filter { x -> Bool in
        print("Filtering: \(x)")
        return x % 3 == 0
    }

let result = Array(lazySequence.prefix(3))
print("Result: \(result)")

// Sequence adapters
let processed = (1...10)
    .dropFirst(2)
    .prefix(5)
    .map { $0 * 2 }
    .filter { $0 % 3 == 0 }

print("Processed: \(Array(processed))")

// Infinite sequence
struct FibonacciSequence: Sequence {
    func makeIterator() -> FibonacciIterator {
        return FibonacciIterator()
    }
}

struct FibonacciIterator: IteratorProtocol {
    var a = 0
    var b = 1
    
    mutating func next() -> Int? {
        let value = a
        let temp = a + b
        a = b
        b = temp
        return value
    }
}

let fib = FibonacciSequence()
let firstTenFib = Array(fib.prefix(10))
print("Fibonacci: \(firstTenFib)")
Advanced
23. What are channels and concurrency?

Swift uses actors and async streams for channel-like communication and concurrency.

  • Actors: actor Counter
  • AsyncStream: Produce values over time
  • AsyncSequence: Iterate over async values
  • Task groups: Group related tasks
  • Continuation: withCheckedContinuation
swift
// Channels and Concurrency in Swift
import Foundation

// Actor for thread-safe state
actor Counter {
    private var value = 0
    
    func increment() {
        value += 1
    }
    
    func getValue() -> Int {
        return value
    }
}

// AsyncStream as channel
func createChannel() -> AsyncStream<Int> {
    return AsyncStream { continuation in
        Task {
            for i in 1...5 {
                try? await Task.sleep(nanoseconds: 100_000_000)
                continuation.yield(i)
            }
            continuation.finish()
        }
    }
}

// AsyncSequence for streaming
struct NumberStream: AsyncSequence {
    typealias Element = Int
    
    let max: Int
    
    func makeAsyncIterator() -> NumberStreamIterator {
        return NumberStreamIterator(max: max)
    }
}

struct NumberStreamIterator: AsyncIteratorProtocol {
    var current = 0
    let max: Int
    
    mutating func next() async -> Int? {
        current += 1
        if current > max {
            return nil
        }
        try? await Task.sleep(nanoseconds: 100_000_000)
        return current
    }
}

// Task group for parallel processing
func processNumbers() async {
    await withTaskGroup(of: String.self) { group in
        for i in 1...5 {
            group.addTask {
                try? await Task.sleep(nanoseconds: 100_000_000)
                return "Task \(i) completed"
            }
        }
        
        for await result in group {
            print(result)
        }
    }
}

// Usage
Task {
    // Actor example
    let counter = Counter()
    await counter.increment()
    await counter.increment()
    print("Counter: \(await counter.getValue())")
    
    // Channel example
    for await value in createChannel() {
        print("Channel: \(value)")
    }
    
    // Async sequence
    for await value in NumberStream(max: 5) {
        print("Stream: \(value)")
    }
    
    // Task group
    await processNumbers()
}
Advanced
24. What are enums and pattern matching?

Enums in Swift are powerful with associated values, pattern matching, and exhaustive switch handling.

  • Associated values: case success(Int)
  • Pattern matching: switch
  • Guard case: guard case
  • If case: if case
  • Recursive enums: indirect enum
swift
// Enums and Pattern Matching in Swift
// Enum with associated values
enum Result<T> {
    case success(T)
    case error(String)
    case loading
}

// Enum with methods
enum Status {
    case success(Int)
    case error(String)
    case loading
    
    func isSuccess() -> Bool {
        switch self {
        case .success:
            return true
        default:
            return false
        }
    }
    
    func getCode() -> Int? {
        if case .success(let code) = self {
            return code
        }
        return nil
    }
}

// Discriminated union pattern
enum UIState {
    case success(data: String)
    case error(message: String)
    case loading
    case idle
}

extension UIState {
    func isLoading() -> Bool {
        if case .loading = self {
            return true
        }
        return false
    }
    
    func getData() -> String? {
        if case .success(let data) = self {
            return data
        }
        return nil
    }
}

// Pattern matching with guards
func processNumber(_ number: Int) {
    switch number {
    case let n where n < 0:
        print("Negative: \(n)")
    case 0:
        print("Zero")
    case let n where n > 0:
        print("Positive: \(n)")
    default:
        print("Unknown")
    }
}

// If let and guard let
func processOptional(_ value: Int?) {
    if let unwrapped = value {
        print("Value: \(unwrapped)")
    }
    
    guard let unwrapped = value else {
        print("Value is nil")
        return
    }
    print("Guard value: \(unwrapped)")
}

// Usage
let result = Result.success(200)
let status = Status.success(200)

if case .success(let code) = status {
    print("Success code: \(code)")
}

switch result {
case .success(let value):
    print("Success: \(value)")
case .error(let message):
    print("Error: \(message)")
case .loading:
    print("Loading...")
}

processNumber(-5)
processOptional(42)
processOptional(nil)
Advanced
25. What are generics in Swift?

Generics allow writing flexible, reusable functions and types that can work with any type.

  • Generic functions: func swap<T>(_ a: T, _ b: T)
  • Generic types: struct Box<T>
  • Constraints: <T: Numeric>
  • Associated types: associatedtype Item
  • Protocol generics: protocol Repository { associatedtype Item }
swift
// Generics in Swift
// Generic struct
struct Box<T> {
    let value: T
    
    func getValue() -> T {
        return value
    }
}

// Generic function
func swap<T>(_ a: T, _ b: T) -> (T, T) {
    return (b, a)
}

// Generic with constraints
func sumNumbers<T: Numeric>(_ items: [T]) -> T {
    return items.reduce(T.zero, +)
}

// Generic with multiple constraints
protocol Displayable {
    func display() -> String
}

protocol Countable {
    func count() -> Int
}

func process<T: Displayable & Countable>(_ item: T) {
    print(item.display())
    print("Count: \(item.count())")
}

// Associated types in protocols
protocol Repository {
    associatedtype Item
    
    func get(id: Int) -> Item?
    func save(item: Item)
}

struct UserRepository: Repository {
    typealias Item = User
    
    func get(id: Int) -> User? {
        return User(id: id, name: "Alice")
    }
    
    func save(item: User) {
        print("Saving user: \(item.name)")
    }
}

// Variance - Covariant (using associated types)
protocol Producer {
    associatedtype T
    func produce() -> T
}

// Contravariant
protocol Consumer {
    associatedtype T
    func consume(item: T)
}

// Usage
let boxInt = Box(value: 42)
let boxString = Box(value: "Hello")

print(boxInt.getValue())
print(boxString.getValue())

let swapped = swap(1, 2)
print("Swapped: \(swapped.0), \(swapped.1)")

let numbers = [1, 2, 3, 4, 5]
print("Sum: \(sumNumbers(numbers))")

struct User {
    let id: Int
    let name: String
}

struct MyData {
    let value: String
}

extension MyData: Displayable, Countable {
    func display() -> String {
        return "Data: \(value)"
    }
    
    func count() -> Int {
        return value.count
    }
}

let data = MyData(value: "Hello")
process(data)
Advanced
26. What are protocols and delegation?

Protocols define blueprints of methods and properties, and delegation is a design pattern using protocols.

  • Protocol: protocol Delegate
  • Delegation: One object delegates tasks
  • Weak delegates: weak var delegate
  • Optional methods: @objc optional
  • Protocol extensions: Default implementations
swift
// Protocols and Delegation in Swift
// Protocol definition
protocol Repository {
    func getData() -> String
    func saveData(_ data: String)
}

// Implementation
class DatabaseRepository: Repository {
    func getData() -> String {
        return "Data from database"
    }
    
    func saveData(_ data: String) {
        print("Saving to database: \(data)")
    }
}

// Delegation using protocol
protocol DataSourceDelegate: AnyObject {
    func dataDidLoad(_ data: [String])
    func dataDidFail(with error: Error)
}

// Class using delegate
class DataSource {
    weak var delegate: DataSourceDelegate?
    
    func loadData() {
        // Simulate async loading
        DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) {
            DispatchQueue.main.async {
                self.delegate?.dataDidLoad(["Item 1", "Item 2", "Item 3"])
            }
        }
    }
}

// Delegate implementation
class ViewController: DataSourceDelegate {
    let dataSource = DataSource()
    
    init() {
        dataSource.delegate = self
        dataSource.loadData()
    }
    
    func dataDidLoad(_ data: [String]) {
        print("Data loaded: \(data)")
    }
    
    func dataDidFail(with error: Error) {
        print("Error: \(error)")
    }
}

// Property delegation using property wrappers
@propertyWrapper
struct Lazy<Value> {
    private var storage: Value?
    private let initializer: () -> Value
    
    init(wrappedValue: @autoclosure @escaping () -> Value) {
        self.initializer = wrappedValue
    }
    
    var wrappedValue: Value {
        mutating get {
            if let value = storage {
                return value
            }
            let value = initializer()
            storage = value
            return value
        }
        set {
            storage = newValue
        }
    }
}

class LazyExample {
    @Lazy(wrappedValue: expensiveComputation())
    var data: String
    
    static func expensiveComputation() -> String {
        print("Computing expensive data...")
        return "Expensive Result"
    }
}

// Usage
let vc = ViewController()

var lazyExample = LazyExample()
print(lazyExample.data)
print(lazyExample.data) // Cached
Advanced
27. What is the singleton pattern in Swift?

Singleton pattern ensures a class has only one instance. It's implemented with a static constant.

  • Static constant: static let shared = Singleton()
  • Private init: private init()
  • Lazy initialization: static var shared: Singleton = ()
  • Thread safety: Guaranteed by Swift
  • Global access: Singleton.shared
swift
// Singleton Pattern in Swift
// Singleton using static constant
class AppConfig {
    static let shared = AppConfig()
    
    private init() {} // Private initializer
    
    var apiUrl = "https://api.example.com"
    var timeout = 5000
    
    func printConfig() {
        print("API URL: \(apiUrl)")
        print("Timeout: \(timeout)")
    }
}

// Singleton with lazy initialization
class UserManager {
    static var shared: UserManager = {
        let instance = UserManager()
        return instance
    }()
    
    private init() {}
    
    private var users: [String] = []
    
    func addUser(_ name: String) {
        users.append(name)
    }
    
    func getUsers() -> [String] {
        return users
    }
}

// Singleton with dispatch_once (using static)
class DatabaseManager {
    static let shared = DatabaseManager()
    
    private init() {
        // Initialize database connection
        print("Database initialized")
    }
    
    func query(_ sql: String) -> String {
        return "Executing: \(sql)"
    }
}

// Usage
let config = AppConfig.shared
config.printConfig()

let manager = UserManager.shared
manager.addUser("Alice")
manager.addUser("Bob")
print("Users: \(manager.getUsers())")

let db = DatabaseManager.shared
print(db.query("SELECT * FROM users"))
Advanced
28. What is the builder pattern in Swift?

Builder pattern constructs complex objects step by step using a fluent interface.

  • Builder class: Constructs objects
  • Fluent interface: Method chaining
  • Director: Orchestrates construction
  • Result builders: DSL for building
  • Product: Final constructed object
swift
// Builder Pattern and DSL in Swift
// Builder pattern
struct User {
    let name: String
    let age: Int
    let email: String
    let city: String
}

class UserBuilder {
    private var name: String = ""
    private var age: Int = 0
    private var email: String = ""
    private var city: String = "Unknown"
    
    func setName(_ name: String) -> UserBuilder {
        self.name = name
        return self
    }
    
    func setAge(_ age: Int) -> UserBuilder {
        self.age = age
        return self
    }
    
    func setEmail(_ email: String) -> UserBuilder {
        self.email = email
        return self
    }
    
    func setCity(_ city: String) -> UserBuilder {
        self.city = city
        return self
    }
    
    func build() -> User {
        return User(name: name, age: age, email: email, city: city)
    }
}

// Fluent interface
struct Query {
    let table: String
    let fields: [String]
    let conditions: [String]
    let orderBy: [String]
    let limit: Int?
    
    static func from(_ table: String) -> QueryBuilder {
        return QueryBuilder(table: table)
    }
}

class QueryBuilder {
    private var table: String
    private var fields: [String] = []
    private var conditions: [String] = []
    private var orderBy: [String] = []
    private var limit: Int?
    
    init(table: String) {
        self.table = table
    }
    
    func select(_ fields: String...) -> QueryBuilder {
        self.fields = fields
        return self
    }
    
    func `where`(_ condition: String) -> QueryBuilder {
        conditions.append(condition)
        return self
    }
    
    func order(by field: String, ascending: Bool = true) -> QueryBuilder {
        let direction = ascending ? "ASC" : "DESC"
        orderBy.append("\(field) \(direction)")
        return self
    }
    
    func limit(_ count: Int) -> QueryBuilder {
        self.limit = count
        return self
    }
    
    func build() -> Query {
        return Query(table: table, fields: fields, conditions: conditions, orderBy: orderBy, limit: limit)
    }
    
    func execute() -> String {
        var query = "SELECT "
        if fields.isEmpty {
            query += "*"
        } else {
            query += fields.joined(separator: ", ")
        }
        query += " FROM \(table)"
        if !conditions.isEmpty {
            query += " WHERE \(conditions.joined(separator: " AND "))"
        }
        if !orderBy.isEmpty {
            query += " ORDER BY \(orderBy.joined(separator: ", "))"
        }
        if let limit = limit {
            query += " LIMIT \(limit)"
        }
        return query
    }
}

// Result builders (DSL)
@resultBuilder
struct HTMLBuilder {
    static func buildBlock(_ components: String...) -> String {
        return components.joined()
    }
}

func html(@HTMLBuilder _ content: () -> String) -> String {
    return "<html>\(content())</html>"
}

func body(@HTMLBuilder _ content: () -> String) -> String {
    return "<body>\(content())</body>"
}

func h1(_ text: String) -> String {
    return "<h1>\(text)</h1>"
}

func p(_ text: String) -> String {
    return "<p>\(text)</p>"
}

// Usage
let user = UserBuilder()
    .setName("Alice")
    .setAge(25)
    .setEmail("alice@example.com")
    .setCity("NYC")
    .build()

print(user)

let query = Query.from("users")
    .select("name", "age")
    .where("age > 18")
    .order(by: "name", ascending: true)
    .limit(10)
    .execute()

print(query)

let page = html {
    body {
        h1("Welcome")
        p("This is a paragraph")
    }
}
print(page)
Advanced
29. What are macros and attributes in Swift?

Macros (Swift 5.9+) generate code at compile time, and attributes provide metadata.

  • Macros: @freestanding, @attached
  • Attributes: @available, @discardableResult
  • Property wrappers: @propertyWrapper
  • Result builders: @resultBuilder
  • Custom attributes: Create custom attributes
swift
// Macros and Attributes in Swift
// Basic macro (Swift 5.9+)
// Note: Macros are a Swift 5.9+ feature

// Stringify macro example
@freestanding(expression)
macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MyMacros", type: "StringifyMacro")

// Usage: let (result, string) = #stringify(42)
// print(result) // 42
// print(string) // "42"

// Attribute macros
@available(iOS 13.0, *)
func newFeature() {
    print("This is a new feature")
}

// Deprecated attribute
@available(*, deprecated, message: "Use newFunction instead")
func oldFunction() {
    print("Old function")
}

// Custom attribute
@propertyWrapper
struct DeprecatedMessage {
    private var value: String
    
    init(wrappedValue: String) {
        self.value = wrappedValue
    }
    
    var wrappedValue: String {
        get { value }
        set { value = newValue }
    }
}

// Result builder attribute
@resultBuilder
struct StringBuilder {
    static func buildBlock(_ components: String...) -> String {
        return components.joined(separator: " ")
    }
}

func buildString(@StringBuilder _ content: () -> String) -> String {
    return content()
}

// Usage
let message = buildString {
    "Hello"
    "World"
    "Swift"
}
print(message)

// Conditional compilation
#if DEBUG
print("Debug mode")
#else
print("Release mode")
#endif

// Platform-specific code
#if os(iOS)
print("Running on iOS")
#elseif os(macOS)
print("Running on macOS")
#endif

// Warning and error macros
#warning("This is a warning")
// #error("This is an error")
Advanced
30. What is reflection in Swift?

Reflection in Swift is provided through Mirror and KeyPath for inspecting types and accessing properties.

  • Mirror: Reflect on types
  • KeyPath: Type-safe property access
  • Dynamic member lookup: @dynamicMemberLookup
  • Codable: Serialization/deserialization
  • Type checking: type(of:)
swift
// Reflection and Type Information in Swift
import Foundation

// Class for reflection examples
class Person {
    let name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func greet() -> String {
        return "Hello, my name is \(name)"
    }
}

// Type checking
func checkType<T, U>(_ type1: T.Type, _ type2: U.Type) -> Bool {
    return type1 == type2
}

// Mirror for reflection
func reflectObject(_ obj: Any) {
    let mirror = Mirror(reflecting: obj)
    print("Type: \(mirror.subjectType)")
    print("Children:")
    for child in mirror.children {
        print("  \(child.label ?? "?") : \(child.value)")
    }
}

// Property access with KeyPath
struct User {
    let name: String
    let age: Int
    let email: String
}

func getProperty<T, V>(_ obj: T, keyPath: KeyPath<T, V>) -> V {
    return obj[keyPath: keyPath]
}

// Dynamic member lookup
@dynamicMemberLookup
struct DynamicObject {
    private var storage: [String: Any] = [:]
    
    subscript(dynamicMember member: String) -> Any? {
        get { storage[member] }
        set { storage[member] = newValue }
    }
}

// Codable for serialization
struct SerializablePerson: Codable {
    let name: String
    let age: Int
    let email: String
}

// Usage
let person = Person(name: "Alice", age: 25)
reflectObject(person)

let user = User(name: "Alice", age: 25, email: "alice@example.com")
let userName = getProperty(user, keyPath: .name)
print("User name: \(userName)")

// Dynamic member lookup
var obj = DynamicObject()
obj.name = "Alice"
obj.age = 25
print(obj.name ?? "nil")
print(obj.age ?? 0)

// Codable serialization
let serializable = SerializablePerson(name: "Alice", age: 25, email: "alice@example.com")
let encoder = JSONEncoder()
if let data = try? encoder.encode(serializable) {
    let json = String(data: data, encoding: .utf8) ?? ""
    print("Serialized: \(json)")
}

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(SerializablePerson.self, from: Data(json.utf8)) {
    print("Decoded: \(decoded)")
}
Coding Round
31. Reverse a string

Reverse a string using reversed() or manual iteration.

  • Built-in: String(str.reversed())
  • Manual: Iterate from end to start
  • Reduce: reduce with string concatenation
  • Complexity: O(n) time
swift
// Reverse a string in Swift
func reverseString(_ str: String) -> String {
    return String(str.reversed())
}

print(reverseString("hello"))  // "olleh"

// Manual implementation
func reverseStringManual(_ str: String) -> String {
    var result = ""
    for char in str {
        result = String(char) + result
    }
    return result
}

print(reverseStringManual("hello"))  // "olleh"

// Using reduce
func reverseStringReduce(_ str: String) -> String {
    return str.reduce("") { String($1) + $0 }
}

print(reverseStringReduce("hello"))  // "olleh"
Coding Round
32. Check palindrome

Check if a string is a palindrome using reversed() or two-pointer approach.

  • reversed(): cleaned == String(cleaned.reversed())
  • Two-pointer: Compare from both ends
  • Case insensitive: lowercased()
  • Ignoring non-alphanumeric: filter { $0.isLetter || $0.isNumber }
swift
// Check palindrome in Swift
func isPalindrome(_ str: String) -> Bool {
    let cleaned = str.lowercased().filter { $0.isLetter || $0.isNumber }
    return cleaned == String(cleaned.reversed())
}

print(isPalindrome("racecar"))  // true
print(isPalindrome("hello"))   // false

// Two-pointer approach
func isPalindromeTwoPointer(_ str: String) -> Bool {
    let chars = Array(str.lowercased().filter { $0.isLetter || $0.isNumber })
    var left = 0
    var right = chars.count - 1
    
    while left < right {
        if chars[left] != chars[right] {
            return false
        }
        left += 1
        right -= 1
    }
    return true
}

print(isPalindromeTwoPointer("A man a plan a canal Panama"))  // true
Coding Round
33. Find max in array

Find maximum using max() or manual iteration.

  • Built-in: arr.max()
  • Manual: Iterate and track max
  • Reduce: reduce(Int.min, max)
  • Complexity: O(n) time
swift
// Find max in array in Swift
func findMax(_ arr: [Int]) -> Int? {
    return arr.max()
}

print(findMax([1, 5, 3, 9, 2]) ?? 0)  // 9

// Manual implementation
func findMaxManual(_ arr: [Int]) -> Int? {
    guard !arr.isEmpty else { return nil }
    var maxVal = arr[0]
    for num in arr {
        if num > maxVal {
            maxVal = num
        }
    }
    return maxVal
}

print(findMaxManual([1, 5, 3, 9, 2]) ?? 0)  // 9

// Using reduce
func findMaxReduce(_ arr: [Int]) -> Int? {
    return arr.reduce(Int.min) { max($0, $1) }
}
Coding Round
34. Remove duplicates

Remove duplicates using Set or filter with contains.

  • Set: Array(Set(arr))
  • Order preserved: filter { seen.insert($0).inserted }
  • Complexity: O(n) time
  • Hashable: Elements must be Hashable
swift
// Remove duplicates in Swift
func removeDuplicates<T: Hashable>(_ arr: [T]) -> [T] {
    return Array(Set(arr))
}

print(removeDuplicates([1, 2, 2, 3, 3, 4]))  // [1, 2, 3, 4]

// Preserving order
func removeDuplicatesOrder<T: Hashable>(_ arr: [T]) -> [T] {
    var seen = Set<T>()
    return arr.filter { seen.insert($0).inserted }
}

print(removeDuplicatesOrder([1, 2, 2, 3, 3, 4]))  // [1, 2, 3, 4]

// Using reduce
func removeDuplicatesReduce<T: Hashable>(_ arr: [T]) -> [T] {
    return arr.reduce(into: []) { result, element in
        if !result.contains(element) {
            result.append(element)
        }
    }
}
Coding Round
35. Merge arrays

Merge arrays using + operator or append(contentsOf:).

  • + operator: arr1 + arr2
  • append: arr1.append(contentsOf: arr2)
  • Unique merge: Array(Set(arr1 + arr2))
  • Complexity: O(n) time
swift
// Merge arrays in Swift
func mergeArrays<T>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return arr1 + arr2
}

print(mergeArrays([1, 2], [3, 4]))  // [1, 2, 3, 4]

// Merge and remove duplicates
func mergeUnique<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return Array(Set(arr1 + arr2))
}

print(mergeUnique([1, 2, 3], [3, 4, 5]))  // [1, 2, 3, 4, 5]

// Preserving order
func mergeUniqueOrder<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    var seen = Set<T>()
    return (arr1 + arr2).filter { seen.insert($0).inserted }
}
Coding Round
36. Convert string to number

Convert using Int() or Double() initializers.

  • Int: Int(str)
  • Double: Double(str)
  • Safe: Returns optional
  • Error handling: Check for nil
swift
// Convert string to number in Swift
func stringToNumber(_ str: String) -> Int? {
    return Int(str)
}

print(stringToNumber("42") ?? 0)  // 42

// Safe conversion
func stringToNumberSafe(_ str: String) -> Int? {
    return Int(str) ?? nil
}

print(stringToNumberSafe("42") ?? 0)  // 42
print(stringToNumberSafe("invalid") ?? 0)  // 0

// Convert to Double
func stringToDouble(_ str: String) -> Double? {
    return Double(str)
}

print(stringToDouble("42.5") ?? 0)  // 42.5
Coding Round
37. Loop through dictionary

Iterate using for-in, keys, values, or forEach.

  • for-in: for (key, value) in dict
  • keys: for key in dict.keys
  • values: for value in dict.values
  • forEach: dict.forEach
swift
// Loop through dictionary in Swift
let dict = ["name": "Alice", "age": "25", "city": "NYC"]

// Using for-in
for (key, value) in dict {
    print("\(key) => \(value)")
}

// Using keys
for key in dict.keys {
    print("\(key) => \(dict[key] ?? "")")
}

// Using values
for value in dict.values {
    print(value)
}

// Using forEach
dict.forEach { key, value in
    print("\(key) => \(value)")
}

// Sorting keys
for key in dict.keys.sorted() {
    print("\(key) => \(dict[key] ?? "")")
}
Coding Round
38. Delay function execution

Delay using DispatchQueue, Timer, or async/await.

  • DispatchQueue: asyncAfter(deadline: .now() + seconds)
  • Timer: scheduledTimer(withTimeInterval:)
  • async/await: Task.sleep(nanoseconds:)
  • RunLoop: RunLoop.current.run(until:)
swift
// Delay function execution in Swift
import Foundation

// Using DispatchQueue
func delayedExecution(seconds: Double, block: @escaping () -> Void) {
    DispatchQueue.global().asyncAfter(deadline: .now() + seconds) {
        block()
    }
}

// Using Timer
func delayedTimer(seconds: TimeInterval, block: @escaping () -> Void) {
    Timer.scheduledTimer(withTimeInterval: seconds, repeats: false) { _ in
        block()
    }
}

// Using async/await
func delay(_ seconds: UInt64) async throws {
    try await Task.sleep(nanoseconds: seconds * 1_000_000_000)
}

// Usage
delayedExecution(seconds: 2) {
    print("After 2 seconds (DispatchQueue)")
}

delayedTimer(seconds: 2) {
    print("After 2 seconds (Timer)")
}

Task {
    try? await delay(2)
    print("After 2 seconds (async/await)")
}

// Keep main thread alive
RunLoop.current.run(until: Date().addingTimeInterval(3))
Coding Round
39. HTTP GET request

HTTP GET using URLSession with completion or async/await.

  • URLSession: dataTask(with:completionHandler:)
  • Async/await: URLSession.shared.data(from:)
  • JSON decoding: JSONDecoder()
  • Error handling: try-catch
swift
// HTTP GET request in Swift
import Foundation

// Using URLSession
func fetchData(url: String, completion: @escaping (Result<Data, Error>) -> Void) {
    guard let url = URL(string: url) else {
        completion(.failure(NSError(domain: "InvalidURL", code: -1)))
        return
    }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        guard let data = data else {
            completion(.failure(NSError(domain: "NoData", code: -2)))
            return
        }
        completion(.success(data))
    }
    task.resume()
}

// Async/await version
func fetchDataAsync(url: String) async throws -> Data {
    guard let url = URL(string: url) else {
        throw NSError(domain: "InvalidURL", code: -1)
    }
    
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

// Decode JSON
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

func fetchUser(id: Int) async throws -> User {
    let url = "https://jsonplaceholder.typicode.com/users/\(id)"
    let data = try await fetchDataAsync(url: url)
    let user = try JSONDecoder().decode(User.self, from: data)
    return user
}

// Usage
fetchData(url: "https://jsonplaceholder.typicode.com/users/1") { result in
    switch result {
    case .success(let data):
        let json = String(data: data, encoding: .utf8) ?? ""
        print("Data: \(json)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

Task {
    do {
        let user = try await fetchUser(id: 1)
        print("User: \(user.name)")
    } catch {
        print("Error: \(error)")
    }
}

// Keep main thread alive
RunLoop.current.run(until: Date().addingTimeInterval(2))
Coding Round
40. Create a promise-like Deferred

Create a Deferred using Deferred class with resolve and reject.

  • Deferred class: Custom implementation
  • resolve: Set success value
  • reject: Set error
  • then: Add callback
swift
// Create a promise-like Deferred in Swift
import Foundation

// Deferred implementation
class Deferred<T> {
    private var value: T?
    private var error: Error?
    private var state: State = .pending
    private var callbacks: [(Result<T, Error>) -> Void] = []
    private let lock = NSLock()
    
    enum State {
        case pending
        case resolved
        case rejected
    }
    
    func resolve(_ value: T) {
        lock.lock()
        defer { lock.unlock() }
        
        guard state == .pending else { return }
        state = .resolved
        self.value = value
        callbacks.forEach { $0(.success(value)) }
        callbacks.removeAll()
    }
    
    func reject(_ error: Error) {
        lock.lock()
        defer { lock.unlock() }
        
        guard state == .pending else { return }
        state = .rejected
        self.error = error
        callbacks.forEach { $0(.failure(error)) }
        callbacks.removeAll()
    }
    
    func then(_ callback: @escaping (Result<T, Error>) -> Void) {
        lock.lock()
        defer { lock.unlock() }
        
        switch state {
        case .pending:
            callbacks.append(callback)
        case .resolved:
            callback(.success(value!))
        case .rejected:
            callback(.failure(error!))
        }
    }
}

// Promise-like function
func createDeferred(shouldResolve: Bool) -> Deferred<String> {
    let deferred = Deferred<String>()
    
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        if shouldResolve {
            deferred.resolve("Success!")
        } else {
            deferred.reject(NSError(domain: "DeferredError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed!"]))
        }
    }
    
    return deferred
}

// Usage
let deferred = createDeferred(shouldResolve: true)
deferred.then { result in
    switch result {
    case .success(let value):
        print("Result: \(value)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

// Keep main thread alive
RunLoop.current.run(until: Date().addingTimeInterval(2))
Coding Round
41. Factorial

Calculate factorial using recursion or iteration.

  • Recursive: n * factorial(n-1)
  • Iterative: Loop with multiplication
  • Base case: n <= 1
  • Edge cases: 0! = 1
swift
// Factorial in Swift
func factorial(_ n: Int) -> Int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n - 1)
}

print(factorial(5))  // 120

// Iterative version
func factorialIterative(_ n: Int) -> Int {
    var result = 1
    for i in 2...n {
        result *= i
    }
    return result
}

print(factorialIterative(5))  // 120

// Using reduce
func factorialReduce(_ n: Int) -> Int {
    return (1...n).reduce(1, *)
}

print(factorialReduce(5))  // 120
Coding Round
42. Fibonacci

Calculate Fibonacci using recursion, iteration, or memoization.

  • Recursive: fib(n-1) + fib(n-2)
  • Iterative: Loop with variables
  • Memoization: Cache results in dictionary
  • Complexity: O(n) with memoization
swift
// Fibonacci in Swift
func fibonacci(_ n: Int) -> Int {
    if n <= 1 {
        return n
    }
    return fibonacci(n - 1) + fibonacci(n - 2)
}

print(fibonacci(8))  // 21

// Iterative version
func fibonacciIterative(_ n: Int) -> Int {
    if n <= 1 {
        return n
    }
    var a = 0, b = 1
    for _ in 2...n {
        let temp = a + b
        a = b
        b = temp
    }
    return b
}

print(fibonacciIterative(8))  // 21

// Memoized version
var fibCache: [Int: Int] = [:]
func fibonacciMemo(_ n: Int) -> Int {
    if n <= 1 {
        return n
    }
    if let cached = fibCache[n] {
        return cached
    }
    let result = fibonacciMemo(n - 1) + fibonacciMemo(n - 2)
    fibCache[n] = result
    return result
}

print(fibonacciMemo(8))  // 21
Coding Round
43. FizzBuzz

FizzBuzz using if-else or switch with modulo operations.

  • Modulo: Check divisibility by 3, 5, 15
  • Order: Check 15 first
  • Range: for i in 1...n
  • Return array: Collect results
swift
// FizzBuzz in Swift
func fizzbuzz(_ n: Int) {
    for i in 1...n {
        if i % 15 == 0 {
            print("FizzBuzz")
        } else if i % 3 == 0 {
            print("Fizz")
        } else if i % 5 == 0 {
            print("Buzz")
        } else {
            print(i)
        }
    }
}

fizzbuzz(15)

// Return as array
func fizzbuzzArray(_ n: Int) -> [String] {
    return (1...n).map { i in
        switch (i % 3 == 0, i % 5 == 0) {
        case (true, true): return "FizzBuzz"
        case (true, false): return "Fizz"
        case (false, true): return "Buzz"
        default: return String(i)
        }
    }
}

print(fizzbuzzArray(15))
Coding Round
44. Find missing number

Find missing number using formula or XOR method.

  • Formula: total - sum
  • XOR: XOR all numbers and indices
  • Complexity: O(n) time
  • Edge cases: Empty array, missing first or last
swift
// Find missing number in Swift
func findMissing(_ arr: [Int]) -> Int {
    let n = arr.count + 1
    let total = n * (n + 1) / 2
    let sum = arr.reduce(0, +)
    return total - sum
}

print(findMissing([1, 2, 4, 5, 6]))  // 3

// Using XOR
func findMissingXOR(_ arr: [Int]) -> Int {
    let n = arr.count + 1
    var xorSum = 0
    for i in 1...n {
        xorSum ^= i
    }
    for num in arr {
        xorSum ^= num
    }
    return xorSum
}

print(findMissingXOR([1, 2, 4, 5, 6]))  // 3
Coding Round
45. Find duplicates

Find duplicates using Set or filter.

  • Set: Track seen elements
  • Filter: arr.filter { !seen.insert($0).inserted }
  • Dictionary: Count occurrences
  • Complexity: O(n) time
swift
// Find duplicates in Swift
func findDuplicates<T: Hashable>(_ arr: [T]) -> [T] {
    var seen = Set<T>()
    var duplicates = Set<T>()
    for item in arr {
        if seen.contains(item) {
            duplicates.insert(item)
        } else {
            seen.insert(item)
        }
    }
    return Array(duplicates)
}

print(findDuplicates([1, 2, 3, 2, 4, 3]))  // [2, 3]

// Using filter
func findDuplicatesFilter<T: Hashable>(_ arr: [T]) -> [T] {
    var seen = Set<T>()
    return arr.filter { !seen.insert($0).inserted }
}

print(findDuplicatesFilter([1, 2, 3, 2, 4, 3]))  // [2, 3]

// Using Dictionary
func findDuplicatesDict<T: Hashable>(_ arr: [T]) -> [T] {
    var counts: [T: Int] = [:]
    for item in arr {
        counts[item, default: 0] += 1
    }
    return counts.filter { $0.value > 1 }.map { $0.key }
}
Coding Round
46. Sum of array

Calculate sum using reduce or manual iteration.

  • reduce: arr.reduce(0, +)
  • Manual: Iterate and accumulate
  • forEach: arr.forEach { total += $0 }
  • Complexity: O(n) time
swift
// Sum of array in Swift
func sumArray(_ arr: [Int]) -> Int {
    return arr.reduce(0, +)
}

print(sumArray([1, 2, 3, 4, 5]))  // 15

// Manual implementation
func sumArrayManual(_ arr: [Int]) -> Int {
    var total = 0
    for num in arr {
        total += num
    }
    return total
}

print(sumArrayManual([1, 2, 3, 4, 5]))  // 15

// Using forEach
func sumArrayForEach(_ arr: [Int]) -> Int {
    var total = 0
    arr.forEach { total += $0 }
    return total
}
Coding Round
47. Average of array

Calculate average using sum divided by count.

  • Method: Double(sum) / Double(arr.count)
  • Empty array: Return 0
  • Precision: Returns Double
  • Manual: Iterate and calculate
swift
// Average of array in Swift
func averageArray(_ arr: [Int]) -> Double {
    guard !arr.isEmpty else { return 0 }
    return Double(arr.reduce(0, +)) / Double(arr.count)
}

print(averageArray([1, 2, 3, 4, 5]))  // 3.0

// Manual implementation
func averageArrayManual(_ arr: [Int]) -> Double {
    guard !arr.isEmpty else { return 0 }
    var total = 0
    for num in arr {
        total += num
    }
    return Double(total) / Double(arr.count)
}

print(averageArrayManual([1, 2, 3, 4, 5]))  // 3.0

// Using floating point
func averageArrayFloat(_ arr: [Double]) -> Double {
    guard !arr.isEmpty else { return 0 }
    return arr.reduce(0, +) / Double(arr.count)
}
Coding Round
48. Sort array ascending

Sort using sorted() or sort().

  • Non-mutating: arr.sorted()
  • Mutating: arr.sort()
  • Custom: sorted { $0 < $1 }
  • Complexity: O(n log n)
swift
// Sort array ascending in Swift
func sortAscending(_ arr: [Int]) -> [Int] {
    return arr.sorted()
}

print(sortAscending([5, 2, 8, 1, 9]))  // [1, 2, 5, 8, 9]

// In-place sorting
func sortAscendingInPlace(_ arr: inout [Int]) {
    arr.sort()
}

var numbers = [5, 2, 8, 1, 9]
sortAscendingInPlace(&numbers)
print(numbers)  // [1, 2, 5, 8, 9]

// Using sorted with closure
func sortAscendingClosure(_ arr: [Int]) -> [Int] {
    return arr.sorted { $0 < $1 }
}
Coding Round
49. Sort array descending

Sort descending using sorted(by: >) or sort(by: >).

  • Non-mutating: arr.sorted(by: >)
  • Mutating: arr.sort(by: >)
  • Custom: sorted { $0 > $1 }
  • Complexity: O(n log n)
swift
// Sort array descending in Swift
func sortDescending(_ arr: [Int]) -> [Int] {
    return arr.sorted(by: >)
}

print(sortDescending([5, 2, 8, 1, 9]))  // [9, 8, 5, 2, 1]

// In-place sorting
func sortDescendingInPlace(_ arr: inout [Int]) {
    arr.sort(by: >)
}

var numbers = [5, 2, 8, 1, 9]
sortDescendingInPlace(&numbers)
print(numbers)  // [9, 8, 5, 2, 1]

// Using sorted with closure
func sortDescendingClosure(_ arr: [Int]) -> [Int] {
    return arr.sorted { $0 > $1 }
}
Coding Round
50. Flatten nested array

Flatten using recursion or flatMap.

  • Recursive: Check if element is array
  • flatMap: arr.flatMap { $0 } (for 2D)
  • Reduce: reduce(into: [])
  • Complexity: O(n) time
swift
// Flatten nested array in Swift
func flattenArray<T>(_ arr: [Any]) -> [T] {
    var result: [T] = []
    for item in arr {
        if let nested = item as? [Any] {
            result += flattenArray(nested)
        } else if let value = item as? T {
            result.append(value)
        }
    }
    return result
}

let nested = [1, [2, [3, 4], 5], 6] as [Any]
let flattened: [Int] = flattenArray(nested)
print(flattened)  // [1, 2, 3, 4, 5, 6]

// Using flatMap (for 2D only)
func flatten2D<T>(_ arr: [[T]]) -> [T] {
    return arr.flatMap { $0 }
}

let nested2D = [[1, 2], [3, 4], [5, 6]]
print(flatten2D(nested2D))  // [1, 2, 3, 4, 5, 6]

// Using reduce
func flattenReduce<T>(_ arr: [Any]) -> [T] {
    return arr.reduce(into: []) { result, item in
        if let nested = item as? [Any] {
            result += flattenReduce(nested) as [T]
        } else if let value = item as? T {
            result.append(value)
        }
    }
}
Coding Round
51. Chunk array

Split array into chunks using stride or manual slicing.

  • stride: stride(from: 0, to: arr.count, by: size)
  • Slice: arr[$0..<min($0 + size, arr.count)]
  • Edge case: Handle last chunk
  • Complexity: O(n) time
swift
// Chunk array in Swift
func chunkArray<T>(_ arr: [T], size: Int) -> [[T]] {
    return stride(from: 0, to: arr.count, by: size).map {
        Array(arr[$0..<min($0 + size, arr.count)])
    }
}

print(chunkArray([1, 2, 3, 4, 5, 6], size: 2))  // [[1, 2], [3, 4], [5, 6]]

// Using while loop
func chunkArrayWhile<T>(_ arr: [T], size: Int) -> [[T]] {
    var result: [[T]] = []
    var i = 0
    while i < arr.count {
        let end = min(i + size, arr.count)
        result.append(Array(arr[i..<end]))
        i += size
    }
    return result
}

print(chunkArrayWhile([1, 2, 3, 4, 5, 6], size: 2))

// With padding
func chunkArrayPadding<T>(_ arr: [T], size: Int, padValue: T) -> [[T]] {
    var chunks = chunkArray(arr, size: size)
    if let last = chunks.last, last.count < size {
        var padded = last
        while padded.count < size {
            padded.append(padValue)
        }
        chunks[chunks.count - 1] = padded
    }
    return chunks
}

print(chunkArrayPadding([1, 2, 3, 4, 5], size: 3, padValue: 0))
Coding Round
53. Quick sort

Quick sort using recursion and partitioning.

  • Algorithm: Choose pivot, partition, recurse
  • Time: O(n log n) average
  • In-place: Implement for performance
  • Pivot: First element or random
swift
// Quick sort in Swift
func quickSort(_ arr: [Int]) -> [Int] {
    if arr.count <= 1 {
        return arr
    }
    let pivot = arr[0]
    let left = arr.filter { $0 < pivot }
    let right = arr.filter { $0 > pivot }
    return quickSort(left) + [pivot] + quickSort(right)
}

print(quickSort([5, 3, 8, 4, 2, 7, 1, 6]))

// In-place quick sort
func quickSortInPlace(_ arr: inout [Int], low: Int, high: Int) {
    if low < high {
        let pi = partition(&arr, low: low, high: high)
        quickSortInPlace(&arr, low: low, high: pi - 1)
        quickSortInPlace(&arr, low: pi + 1, high: high)
    }
}

func partition(_ arr: inout [Int], low: Int, high: Int) -> Int {
    let pivot = arr[high]
    var i = low - 1
    for j in low..<high {
        if arr[j] <= pivot {
            i += 1
            arr.swapAt(i, j)
        }
    }
    arr.swapAt(i + 1, high)
    return i + 1
}

var numbers = [5, 3, 8, 4, 2, 7, 1, 6]
quickSortInPlace(&numbers, low: 0, high: numbers.count - 1)
print(numbers)
Coding Round
54. Merge sort

Merge sort using divide-and-conquer and merging.

  • Algorithm: Divide, sort, merge
  • Time: O(n log n)
  • Stable: Maintains relative order
  • Space: O(n) auxiliary space
swift
// Merge sort in Swift
func mergeSort(_ arr: [Int]) -> [Int] {
    if arr.count <= 1 {
        return arr
    }
    let mid = arr.count / 2
    let left = mergeSort(Array(arr[0..<mid]))
    let right = mergeSort(Array(arr[mid..<arr.count]))
    return merge(left, right)
}

func merge(_ left: [Int], _ right: [Int]) -> [Int] {
    var result: [Int] = []
    var i = 0, j = 0
    
    while i < left.count && j < right.count {
        if left[i] <= right[j] {
            result.append(left[i])
            i += 1
        } else {
            result.append(right[j])
            j += 1
        }
    }
    
    result.append(contentsOf: left[i...])
    result.append(contentsOf: right[j...])
    return result
}

print(mergeSort([5, 3, 8, 4, 2, 7, 1, 6]))
Coding Round
55. Bubble sort

Bubble sort with early termination optimization.

  • Algorithm: Compare adjacent, swap
  • Time: O(n²) worst case
  • Optimization: Stop if no swaps
  • In-place: Modifies original array
swift
// Bubble sort in Swift
func bubbleSort(_ arr: [Int]) -> [Int] {
    var sorted = arr
    for i in 0..<sorted.count - 1 {
        for j in 0..<sorted.count - 1 - i {
            if sorted[j] > sorted[j + 1] {
                sorted.swapAt(j, j + 1)
            }
        }
    }
    return sorted
}

print(bubbleSort([5, 3, 8, 4, 2, 7, 1, 6]))

// Optimized bubble sort
func bubbleSortOptimized(_ arr: [Int]) -> [Int] {
    var sorted = arr
    for i in 0..<sorted.count - 1 {
        var swapped = false
        for j in 0..<sorted.count - 1 - i {
            if sorted[j] > sorted[j + 1] {
                sorted.swapAt(j, j + 1)
                swapped = true
            }
        }
        if !swapped {
            break
        }
    }
    return sorted
}

print(bubbleSortOptimized([5, 3, 8, 4, 2, 7, 1, 6]))
Coding Round
56. Intersection of arrays

Find common elements using Set or filter.

  • Set: Array(Set(arr1).intersection(Set(arr2)))
  • Filter: arr1.filter { arr2.contains($0) }
  • Complexity: O(n) time with Set
  • Return: Array of common elements
swift
// Intersection of arrays in Swift
func intersection<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    let set2 = Set(arr2)
    return arr1.filter { set2.contains($0) }
}

print(intersection([1, 2, 3, 4], [3, 4, 5, 6]))  // [3, 4]

// Using Set
func intersectionSet<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    let set1 = Set(arr1)
    let set2 = Set(arr2)
    return Array(set1.intersection(set2))
}

print(intersectionSet([1, 2, 3, 4], [3, 4, 5, 6]))  // [3, 4]

// Using filter
func intersectionFilter<T: Equatable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return arr1.filter { arr2.contains($0) }
}
Coding Round
57. Union of arrays

Combine arrays with unique elements using Set.

  • Set: Array(Set(arr1).union(Set(arr2)))
  • Preserve order: Use filter with Set
  • Complexity: O(n) time
  • Return: Array of unique elements
swift
// Union of arrays in Swift
func union<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return Array(Set(arr1).union(Set(arr2)))
}

print(union([1, 2, 3], [3, 4, 5]))  // [1, 2, 3, 4, 5]

// Preserving order
func unionOrder<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    var result = arr1
    for item in arr2 where !result.contains(item) {
        result.append(item)
    }
    return result
}

print(unionOrder([1, 2, 3], [3, 4, 5]))  // [1, 2, 3, 4, 5]

// Using reduce
func unionReduce<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return arr1 + arr2.filter { !arr1.contains($0) }
}
Coding Round
58. Difference of arrays

Find elements in first array not in second using Set.

  • Set: Array(Set(arr1).subtracting(Set(arr2)))
  • Filter: arr1.filter { !arr2.contains($0) }
  • Symmetric difference: symmetricDifference
  • Complexity: O(n) time
swift
// Difference of arrays in Swift
func difference<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    let set2 = Set(arr2)
    return arr1.filter { !set2.contains($0) }
}

print(difference([1, 2, 3, 4], [3, 4, 5, 6]))  // [1, 2]

// Symmetric difference
func symmetricDifference<T: Hashable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    let set1 = Set(arr1)
    let set2 = Set(arr2)
    return Array(set1.symmetricDifference(set2))
}

print(symmetricDifference([1, 2, 3], [3, 4, 5]))  // [1, 2, 4, 5]

// Using filter
func differenceFilter<T: Equatable>(_ arr1: [T], _ arr2: [T]) -> [T] {
    return arr1.filter { !arr2.contains($0) }
}
Coding Round
59. Group by property

Group objects by property using Dictionary(grouping:).

  • Dictionary: Dictionary(grouping: items, by: { $0.type })
  • KeyPath: Use KeyPath for grouping
  • Complexity: O(n) time
  • Return: Dictionary with grouped items
swift
// Group by property in Swift
struct Item {
    let type: String
    let name: String
}

func groupByProperty(_ items: [Item], keyPath: KeyPath<Item, String>) -> [String: [Item]] {
    return Dictionary(grouping: items, by: { $0[keyPath: keyPath] })
}

// Usage
let data = [
    Item(type: "fruit", name: "apple"),
    Item(type: "fruit", name: "banana"),
    Item(type: "veg", name: "carrot")
]

let groups = groupByProperty(data, keyPath: .type)
for (key, items) in groups {
    print("\(key): \(items.map { $0.name })")
}

// Using Dictionary grouping
func groupByType(_ items: [Item]) -> [String: [Item]] {
    return Dictionary(grouping: items) { $0.type }
}

print(groupByType(data))

// Group with count
func groupByPropertyCount(_ items: [Item], keyPath: KeyPath<Item, String>) -> [String: Int] {
    let groups = Dictionary(grouping: items, by: { $0[keyPath: keyPath] })
    return groups.mapValues { $0.count }
}

print(groupByPropertyCount(data, keyPath: .type))
Coding Round
60. Deep clone object

Deep clone using Codable or manual copy.

  • Codable: JSONDecoder().decode(T.self, from: JSONEncoder().encode(obj))
  • Manual: Recursive copy
  • NSCopying: Implement copy protocol
  • Benefits: Complete independent copy
swift
// Deep clone in Swift
struct Address {
    var city: String
    var zip: String
}

struct User {
    var name: String
    var address: Address
}

func deepClone<T: Codable>(_ obj: T) throws -> T {
    let encoder = JSONEncoder()
    let data = try encoder.encode(obj)
    let decoder = JSONDecoder()
    return try decoder.decode(T.self, from: data)
}

// Manual deep clone
func manualDeepClone(_ user: User) -> User {
    return User(
        name: user.name,
        address: Address(city: user.address.city, zip: user.address.zip)
    )
}

// Usage
let original = User(
    name: "Alice",
    address: Address(city: "NYC", zip: "10001")
)

let cloned = manualDeepClone(original)
var clonedMutable = cloned
clonedMutable.name = "Bob"
clonedMutable.address.city = "LA"

print("Original: \(original)")
print("Cloned: \(clonedMutable)")
Coding Round
61. Immutable update

Perform immutable updates using struct copy or with function.

  • Struct copy: Copy and modify
  • with: with(state) { $0.user.age = 26 }
  • KeyPath: Update using KeyPath
  • Return: New immutable object
swift
// Immutable update in Swift
struct User {
    var name: String
    var age: Int
}

struct State {
    var user: User
}

func updateImmutable(_ state: State, keyPath: WritableKeyPath<State, Int>, value: Int) -> State {
    var newState = state
    newState[keyPath: keyPath] = value
    return newState
}

// Usage
let state = State(user: User(name: "Alice", age: 25))
let newState = updateImmutable(state, keyPath: .user.age, value: 26)

print("Original: \(state.user.age)")
print("New: \(newState.user.age)")

// Using with function
func with<T>(_ obj: T, update: (inout T) -> Void) -> T {
    var mutable = obj
    update(&mutable)
    return mutable
}

let state2 = with(state) { $0.user.age = 27 }
print("With: \(state2.user.age)")
Coding Round
62. Pipe function

Pipe composes functions from left to right.

  • Implementation: transforms.reduce(value) { $1($0) }
  • Operator: Custom |> operator
  • Return: Function that chains operations
  • Direction: Left to right
swift
// Pipe function in Swift
func pipe<T>(_ value: T, _ transforms: [(T) -> T]) -> T {
    return transforms.reduce(value) { $1($0) }
}

func pipe<T, U, V>(_ f: @escaping (T) -> U, _ g: @escaping (U) -> V) -> (T) -> V {
    return { g(f($0)) }
}

// Usage
let double = { (x: Int) -> Int in x * 2 }
let addTen = { (x: Int) -> Int in x + 10 }
let square = { (x: Int) -> Int in x * x }

let process = pipe(double, addTen, square)
let result = process(5)
print(result)  // (5*2+10)^2 = 400

// Using array of transforms
let transforms: [(Int) -> Int] = [double, addTen, square]
let result2 = pipe(5, transforms)
print(result2)  // 400

// Custom pipe operator
infix operator |> : AdditionPrecedence
func |> <T, U>(value: T, transform: (T) -> U) -> U {
    return transform(value)
}

let result3 = 5 |> double |> addTen |> square
print(result3)  // 400
Coding Round
63. Compose function

Compose functions from right to left.

  • Implementation: transforms.reversed().reduce(value) { $1($0) }
  • Operator: Custom >>> operator
  • Return: Function that chains operations
  • Direction: Right to left
swift
// Compose function in Swift
func compose<T, U, V>(_ f: @escaping (U) -> V, _ g: @escaping (T) -> U) -> (T) -> V {
    return { f(g($0)) }
}

// Usage
let double = { (x: Int) -> Int in x * 2 }
let addTen = { (x: Int) -> Int in x + 10 }
let square = { (x: Int) -> Int in x * x }

let squareThenAddTen = compose(addTen, square)
let result = squareThenAddTen(5)
print(result)  // (5^2 + 10) = 35

// Variadic compose
func composeVariadic<T>(_ transforms: [(T) -> T]) -> (T) -> T {
    return { value in
        transforms.reversed().reduce(value) { $1($0) }
    }
}

let process = composeVariadic([double, addTen, square])
let result2 = process(5)
print(result2)  // (5*2+10)^2 = 400

// Custom compose operator
infix operator >>> : AdditionPrecedence
func >>> <T, U, V>(f: @escaping (U) -> V, g: @escaping (T) -> U) -> (T) -> V {
    return { f(g($0)) }
}

let process3 = addTen >>> double >>> square
let result3 = process3(5)
print(result3)  // (5*2+10)^2 = 400
Coding Round
64. Memoization

Cache function results based on arguments using dictionary.

  • Cache: [T: U]
  • Key: Function arguments
  • Return: Cached or computed result
  • Trade-off: Memory for speed
swift
// Memoization in Swift
func memoize<T: Hashable, U>(_ function: @escaping (T) -> U) -> (T) -> U {
    var cache: [T: U] = [:]
    return { input in
        if let cached = cache[input] {
            return cached
        }
        let result = function(input)
        cache[input] = result
        return result
    }
}

// Fibonacci with memoization
let fibMemo = memoize { (n: Int) -> Int in
    if n <= 1 {
        return n
    }
    return fibMemo(n - 1) + fibMemo(n - 2)
}

print(fibMemo(10))  // 55

// Memoize with class
class Memoizer<T: Hashable, U> {
    private var cache: [T: U] = [:]
    private let function: (T) -> U
    
    init(function: @escaping (T) -> U) {
        self.function = function
    }
    
    func call(_ input: T) -> U {
        if let cached = cache[input] {
            return cached
        }
        let result = function(input)
        cache[input] = result
        return result
    }
}

let fibMemoizer = Memoizer { (n: Int) -> Int in
    if n <= 1 {
        return n
    }
    return fibMemoizer.call(n - 1) + fibMemoizer.call(n - 2)
}

print(fibMemoizer.call(10))  // 55
Coding Round
65. Once function

Ensure a function is called only once using closure.

  • Closure: var called = false
  • Result: Cache the result
  • Return: Function with guard
  • Use case: Initialization
swift
// Once function in Swift
func once<T>(_ function: @autoclosure @escaping () -> T) -> () -> T {
    var called = false
    var result: T?
    return {
        if !called {
            called = true
            result = function()
        }
        return result!
    }
}

// Usage
let initialize = once {
    print("Initialized")
    return 42
}

print(initialize())  // Prints "Initialized", returns 42
print(initialize())  // Returns 42 (cached)

// Once with class
class Once<T> {
    private var called = false
    private var result: T?
    private let function: () -> T
    
    init(function: @escaping () -> T) {
        self.function = function
    }
    
    func call() -> T {
        if !called {
            called = true
            result = function()
        }
        return result!
    }
}

let onceInstance = Once { 
    print("Initialized 2")
    return "Hello"
}

print(onceInstance.call())  // Prints "Initialized 2"
print(onceInstance.call())  // Returns cached
Coding Round
66. Debounce with leading edge

Debounce with leading edge using timer and timestamp.

  • Timer: Timer for delayed execution
  • Leading edge: Execute immediately
  • Cooldown: Wait before next execution
  • Use case: Search input, API calls
swift
// Debounce with leading edge in Swift
import Foundation

func debounceLeading<T>(delay: TimeInterval, action: @escaping (T) -> Void) -> (T) -> Void {
    var lastCall: Date = Date()
    var timer: Timer?
    
    return { input in
        let now = Date()
        if now.timeIntervalSince(lastCall) < delay {
            timer?.invalidate()
            timer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { _ in
                lastCall = Date()
                action(input)
            }
        } else {
            lastCall = now
            action(input)
        }
    }
}

// Usage
let debounced = debounceLeading(delay: 1.0) { value in
    print("Executed: \(value)")
}

debounced("First")  // Executes immediately
debounced("Second") // Scheduled for later
debounced("Third")  // Scheduled for later

// Keep main thread alive
RunLoop.current.run(until: Date().addingTimeInterval(2))
Coding Round
67. Throttle with leading edge

Throttle with leading edge using timestamp tracking.

  • Timestamp: Track last execution time
  • Leading edge: Execute if enough time passed
  • Rate limiting: At most once per period
  • Use case: Scroll events, resize
swift
// Throttle with leading edge in Swift
import Foundation

func throttleLeading<T>(delay: TimeInterval, action: @escaping (T) -> Void) -> (T) -> Void {
    var lastCall: Date = Date()
    
    return { input in
        let now = Date()
        if now.timeIntervalSince(lastCall) >= delay {
            lastCall = now
            action(input)
        }
    }
}

// Usage
let throttled = throttleLeading(delay: 1.0) { value in
    print("Executed: \(value)")
}

throttled("First")   // Executes
throttled("Second")  // Ignored (within 1 second)
throttled("Third")   // Ignored (within 1 second)

// Keep main thread alive
RunLoop.current.run(until: Date().addingTimeInterval(2))
Coding Round
68. Deep equal

Deep equality comparison using Equatable protocol.

  • Equatable: extension User: Equatable
  • Manual: Recursive comparison
  • Arrays: Compare elements recursively
  • Objects: Compare fields recursively
swift
// Deep equal in Swift
func deepEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
    return a == b
}

// For custom structs, conform to Equatable
struct Address: Equatable {
    let city: String
    let zip: String
}

struct User: Equatable {
    let name: String
    let address: Address
}

// Usage
let user1 = User(name: "Alice", address: Address(city: "NYC", zip: "10001"))
let user2 = User(name: "Alice", address: Address(city: "NYC", zip: "10001"))
let user3 = User(name: "Bob", address: Address(city: "LA", zip: "90001"))

print(deepEqual(user1, user2))  // true
print(deepEqual(user1, user3))  // false

// Manual deep equal for arrays
func deepEqualArray<T: Equatable>(_ a: [T], _ b: [T]) -> Bool {
    guard a.count == b.count else { return false }
    for (item1, item2) in zip(a, b) {
        if item1 != item2 {
            return false
        }
    }
    return true
}

let arr1 = [1, 2, 3]
let arr2 = [1, 2, 3]
let arr3 = [1, 2, 4]

print(deepEqualArray(arr1, arr2))  // true
print(deepEqualArray(arr1, arr3))  // false
Coding Round
69. Observable pattern

Observable pattern with subscribers and notifications.

  • Observable: Maintains subscribers
  • Subscribe: Add callback
  • Notify: Call all subscribers
  • Unsubscribe: Remove callback
swift
// Observable pattern in Swift
class Observable<T> {
    private var observers: [(T) -> Void] = []
    private var value: T
    
    init(_ value: T) {
        self.value = value
    }
    
    func subscribe(_ observer: @escaping (T) -> Void) -> () -> Void {
        observers.append(observer)
        observer(value) // Immediately notify with current value
        return {
            self.observers.removeAll { $0 as AnyObject === observer as AnyObject }
        }
    }
    
    func update(_ newValue: T) {
        value = newValue
        observers.forEach { $0(newValue) }
    }
}

// Usage
let observable = Observable("Hello")
let unsubscribe = observable.subscribe { value in
    print("Observer received: \(value)")
}

observable.update("World")  // Prints "Observer received: World"
unsubscribe()
observable.update("Again")  // Nothing happens

// Multiple observers
let observable2 = Observable(0)
observable2.subscribe { value in
    print("Observer 1: \(value)")
}
observable2.subscribe { value in
    print("Observer 2: \(value)")
}
observable2.update(42)
Coding Round
70. Singleton pattern

Singleton pattern using static constant.

  • Static constant: static let shared = Singleton()
  • Private init: private init()
  • Lazy initialization: static var shared: Singleton = ()
  • Global access: Singleton.shared
swift
// Singleton pattern in Swift
class Singleton {
    static let shared = Singleton()
    private init() {} // Private initializer
    
    private var data: [String: Any] = [:]
    
    func set(_ key: String, value: Any) {
        data[key] = value
    }
    
    func get(_ key: String) -> Any? {
        return data[key]
    }
}

// Usage
let singleton1 = Singleton.shared
let singleton2 = Singleton.shared

singleton1.set("name", value: "Alice")
print(singleton2.get("name") ?? "nil")  // Alice
print(singleton1 === singleton2)  // true

// Singleton with lazy initialization
class LazySingleton {
    static var shared: LazySingleton = {
        let instance = LazySingleton()
        // Additional setup
        return instance
    }()
    
    private init() {}
}

// Singleton with dispatch_once (using static)
class DatabaseSingleton {
    static let shared = DatabaseSingleton()
    private init() {
        print("Database initialized")
    }
}
Coding Round
71. Factory pattern

Factory pattern using static methods.

  • Factory method: static func create(type: String) -> User
  • Type parameter: Determines which class
  • Return: Instance of requested type
  • Benefits: Decouples creation logic
swift
// Factory pattern in Swift
protocol User {
    var name: String { get }
    func getRole() -> String
}

struct Admin: User {
    let name: String
    func getRole() -> String { return "admin" }
}

struct Guest: User {
    let name: String
    func getRole() -> String { return "guest" }
}

struct RegularUser: User {
    let name: String
    func getRole() -> String { return "regular" }
}

class UserFactory {
    static func createUser(type: String, name: String) -> User {
        switch type {
        case "admin":
            return Admin(name: name)
        case "guest":
            return Guest(name: name)
        default:
            return RegularUser(name: name)
        }
    }
}

// Usage
let admin = UserFactory.createUser(type: "admin", name: "Alice")
let guest = UserFactory.createUser(type: "guest", name: "Bob")

print("\(admin.name) role: \(admin.getRole())")
print("\(guest.name) role: \(guest.getRole())")

// Abstract factory
protocol Widget {
    func draw()
}

struct Button: Widget {
    func draw() { print("Drawing Button") }
}

struct TextField: Widget {
    func draw() { print("Drawing TextField") }
}

class WidgetFactory {
    static func createWidget(type: String) -> Widget? {
        switch type {
        case "button":
            return Button()
        case "textfield":
            return TextField()
        default:
            return nil
        }
    }
}

let button = WidgetFactory.createWidget(type: "button")
button?.draw()
Coding Round
72. Strategy pattern

Strategy pattern using protocols.

  • Strategy protocol: Define algorithm interface
  • Concrete strategies: Implement protocol
  • Context: Uses strategy
  • Runtime switching: Change strategy at runtime
swift
// Strategy pattern in Swift
protocol PaymentStrategy {
    func pay(amount: Double)
}

struct CreditCardStrategy: PaymentStrategy {
    func pay(amount: Double) {
        print("Paid $\(amount) with Credit Card")
    }
}

struct PayPalStrategy: PaymentStrategy {
    func pay(amount: Double) {
        print("Paid $\(amount) with PayPal")
    }
}

struct CryptoStrategy: PaymentStrategy {
    func pay(amount: Double) {
        print("Paid $\(amount) with Crypto")
    }
}

class PaymentContext {
    private var strategy: PaymentStrategy
    
    init(strategy: PaymentStrategy) {
        self.strategy = strategy
    }
    
    func setStrategy(_ strategy: PaymentStrategy) {
        self.strategy = strategy
    }
    
    func executePayment(amount: Double) {
        strategy.pay(amount: amount)
    }
}

// Usage
let context = PaymentContext(strategy: CreditCardStrategy())
context.executePayment(amount: 100.0)

context.setStrategy(PayPalStrategy())
context.executePayment(amount: 50.0)

context.setStrategy(CryptoStrategy())
context.executePayment(amount: 75.0)

// Strategy with closures
typealias PaymentClosure = (Double) -> Void

let creditCardPayment: PaymentClosure = { amount in
    print("Paid $\(amount) with Credit Card")
}

let payPalPayment: PaymentClosure = { amount in
    print("Paid $\(amount) with PayPal")
}

creditCardPayment(100)
payPalPayment(50)
Coding Round
73. Observer pattern

Observer pattern with subject and observers.

  • Subject: Maintains observers
  • Observer protocol: Defines update method
  • Attach/Detach: Add/remove observers
  • Notify: Call update on all observers
swift
// Observer pattern in Swift
protocol Observer: AnyObject {
    func update(data: String)
}

class Subject {
    private var observers: [Observer] = []
    private(set) var state: String = "" {
        didSet {
            notifyObservers()
        }
    }
    
    func attach(_ observer: Observer) {
        observers.append(observer)
    }
    
    func detach(_ observer: Observer) {
        observers.removeAll { $0 === observer }
    }
    
    func setState(_ state: String) {
        self.state = state
    }
    
    private func notifyObservers() {
        observers.forEach { $0.update(data: state) }
    }
}

class ConcreteObserver: Observer {
    let name: String
    
    init(name: String) {
        self.name = name
    }
    
    func update(data: String) {
        print("\(name) received: \(data)")
    }
}

// Usage
let subject = Subject()
let observer1 = ConcreteObserver(name: "Observer1")
let observer2 = ConcreteObserver(name: "Observer2")

subject.attach(observer1)
subject.attach(observer2)

subject.setState("Hello World")

subject.detach(observer1)
subject.setState("Hello again")

// Using closures for observer
class ClosureSubject {
    private var observers: [(String) -> Void] = []
    private(set) var state: String = "" {
        didSet {
            observers.forEach { $0(state) }
        }
    }
    
    func subscribe(_ observer: @escaping (String) -> Void) -> () -> Void {
        observers.append(observer)
        return {
            self.observers.removeAll { $0 as AnyObject === observer as AnyObject }
        }
    }
    
    func setState(_ state: String) {
        self.state = state
    }
}

let closureSubject = ClosureSubject()
let unsubscribe = closureSubject.subscribe { data in
    print("Closure observer received: \(data)")
}
closureSubject.setState("Hello Closure")
unsubscribe()
closureSubject.setState("Again")
Coding Round
74. Decorator pattern

Decorator pattern using wrapper structs.

  • Component: Base object
  • Decorator: Wraps component
  • Chaining: Multiple decorators
  • Benefits: Add behavior dynamically
swift
// Decorator pattern in Swift
protocol Coffee {
    var cost: Double { get }
    var description: String { get }
}

struct SimpleCoffee: Coffee {
    let cost: Double = 5.0
    let description: String = "Coffee"
}

struct MilkDecorator: Coffee {
    let coffee: Coffee
    
    var cost: Double {
        return coffee.cost + 2.0
    }
    
    var description: String {
        return "\(coffee.description), Milk"
    }
}

struct SugarDecorator: Coffee {
    let coffee: Coffee
    
    var cost: Double {
        return coffee.cost + 1.0
    }
    
    var description: String {
        return "\(coffee.description), Sugar"
    }
}

struct WhippedCreamDecorator: Coffee {
    let coffee: Coffee
    
    var cost: Double {
        return coffee.cost + 1.5
    }
    
    var description: String {
        return "\(coffee.description), Whipped Cream"
    }
}

// Usage
var coffee: Coffee = SimpleCoffee()
coffee = MilkDecorator(coffee: coffee)
coffee = SugarDecorator(coffee: coffee)
coffee = WhippedCreamDecorator(coffee: coffee)

print(coffee.description)  // Coffee, Milk, Sugar, Whipped Cream
print(coffee.cost)  // 9.5

// Using function decorators
func milkDecorator(_ coffee: Coffee) -> Coffee {
    return MilkDecorator(coffee: coffee)
}

func sugarDecorator(_ coffee: Coffee) -> Coffee {
    return SugarDecorator(coffee: coffee)
}

var coffee2: Coffee = SimpleCoffee()
coffee2 = milkDecorator(coffee2)
coffee2 = sugarDecorator(coffee2)
print(coffee2.description)  // Coffee, Milk, Sugar
Coding Round
75. Command pattern

Command pattern with execute and undo methods.

  • Command protocol: Execute and undo
  • Receiver: Performs actual work
  • Invoker: Executes commands
  • Undo/Redo: Command history
swift
// Command pattern in Swift
protocol Command {
    func execute()
    func undo()
}

class AddCommand: Command {
    private var receiver: [Int]
    private let value: Int
    
    init(receiver: inout [Int], value: Int) {
        self.receiver = receiver
        self.value = value
    }
    
    func execute() {
        receiver.append(value)
    }
    
    func undo() {
        if let index = receiver.firstIndex(of: value) {
            receiver.remove(at: index)
        }
    }
}

// Command manager for undo/redo
class CommandManager {
    private var history: [Command] = []
    private var redoStack: [Command] = []
    
    func execute(_ command: Command) {
        command.execute()
        history.append(command)
        redoStack.removeAll()
    }
    
    func undo() {
        guard let command = history.last else { return }
        command.undo()
        history.removeLast()
        redoStack.append(command)
    }
    
    func redo() {
        guard let command = redoStack.last else { return }
        command.execute()
        redoStack.removeLast()
        history.append(command)
    }
}

// Usage
var receiver = [1, 2, 3]
let manager = CommandManager()

let addCommand = AddCommand(receiver: &receiver, value: 4)
manager.execute(addCommand)
print(receiver)  // [1, 2, 3, 4]

manager.undo()
print(receiver)  // [1, 2, 3]

manager.redo()
print(receiver)  // [1, 2, 3, 4]
Coding Round
76. Memento pattern

Memento pattern for state capture and restoration.

  • Originator: Creates and restores mementos
  • Memento: Stores state
  • Caretaker: Manages mementos
  • Undo/Redo: State history
swift
// Memento pattern in Swift
class Memento {
    let state: String
    init(state: String) {
        self.state = state
    }
}

class Originator {
    var state: String = ""
    
    func saveState() -> Memento {
        return Memento(state: state)
    }
    
    func restoreState(_ memento: Memento) {
        state = memento.state
    }
}

class Caretaker {
    private var mementos: [Memento] = []
    
    func addMemento(_ memento: Memento) {
        mementos.append(memento)
    }
    
    func getMemento(at index: Int) -> Memento? {
        guard index < mementos.count else { return nil }
        return mementos[index]
    }
}

// Usage
let originator = Originator()
let caretaker = Caretaker()

originator.state = "State 1"
caretaker.addMemento(originator.saveState())

originator.state = "State 2"
caretaker.addMemento(originator.saveState())

originator.state = "State 3"

if let memento = caretaker.getMemento(at: 0) {
    originator.restoreState(memento)
    print("Restored: \(originator.state)")  // State 1
}

// Memento with Codable
struct CodableMemento<T: Codable>: Codable {
    let state: T
}

class CodableOriginator<T: Codable> {
    var state: T
    
    init(state: T) {
        self.state = state
    }
    
    func saveState() -> CodableMemento<T> {
        return CodableMemento(state: state)
    }
    
    func restoreState(_ memento: CodableMemento<T>) {
        state = memento.state
    }
}
Coding Round
77. Mediator pattern

Mediator pattern for centralized communication.

  • Mediator: Encapsulates communication
  • Colleague: Communicates through mediator
  • Benefits: Loose coupling
  • Use case: Chat systems
swift
// Mediator pattern in Swift
class Mediator {
    private var colleagues: [Colleague] = []
    
    func register(_ colleague: Colleague) {
        colleagues.append(colleague)
        colleague.mediator = self
    }
    
    func send(message: String, from sender: Colleague) {
        colleagues.forEach { colleague in
            if colleague !== sender {
                colleague.receive(message: message)
            }
        }
    }
}

class Colleague {
    let name: String
    weak var mediator: Mediator?
    
    init(name: String) {
        self.name = name
    }
    
    func send(message: String) {
        mediator?.send(message: message, from: self)
    }
    
    func receive(message: String) {
        print("\(name) received: \(message)")
    }
}

// Usage
let mediator = Mediator()
let alice = Colleague(name: "Alice")
let bob = Colleague(name: "Bob")

mediator.register(alice)
mediator.register(bob)

alice.send(message: "Hello Bob!")

// Chat room mediator
class ChatRoom: Mediator {
    private var history: [String] = []
    
    override func send(message: String, from sender: Colleague) {
        history.append("\(sender.name): \(message)")
        super.send(message: message, from: sender)
    }
    
    func getHistory() -> [String] {
        return history
    }
}

let chatRoom = ChatRoom()
let user1 = Colleague(name: "User1")
let user2 = Colleague(name: "User2")

chatRoom.register(user1)
chatRoom.register(user2)

user1.send(message: "Hello everyone!")
print(chatRoom.getHistory())
Coding Round
78. Chain of Responsibility

Chain of Responsibility using protocols.

  • Handler: Processes or forwards
  • Chain: Linked list of handlers
  • Benefits: Decoupling
  • Use case: Logging, authentication
swift
// Chain of Responsibility in Swift
protocol Handler {
    var nextHandler: Handler? { get set }
    func handle(request: [String: Any])
}

extension Handler {
    mutating func setNext(_ handler: Handler) -> Handler {
        self.nextHandler = handler
        return handler
    }
}

class AuthHandler: Handler {
    var nextHandler: Handler?
    
    func handle(request: [String: Any]) {
        if let _ = request["token"] {
            print("Authentication passed")
            nextHandler?.handle(request: request)
        } else {
            print("Authentication failed")
        }
    }
}

class LoggerHandler: Handler {
    var nextHandler: Handler?
    
    func handle(request: [String: Any]) {
        print("Logging request: \(request["url"] ?? "unknown")")
        nextHandler?.handle(request: request)
    }
}

class PermissionHandler: Handler {
    var nextHandler: Handler?
    
    func handle(request: [String: Any]) {
        if let permissions = request["permissions"] as? [String],
           permissions.contains("read") {
            print("Permission granted")
            nextHandler?.handle(request: request)
        } else {
            print("Permission denied")
        }
    }
}

// Usage
var auth = AuthHandler()
var logger = LoggerHandler()
var permission = PermissionHandler()

auth.nextHandler = logger
logger.nextHandler = permission

auth.handle(request: [
    "token": "valid",
    "url": "/api/data",
    "permissions": ["read"]
])
Coding Round
79. State pattern

State pattern for changing behavior with state.

  • Context: Maintains state
  • State: Defines behavior
  • Transitions: Change between states
  • Benefits: Clean state management
swift
// State pattern in Swift
protocol State {
    func handle(context: Context)
}

class ReadyState: State {
    func handle(context: Context) {
        print("Ready: Waiting for input")
        context.state = ProcessingState()
    }
}

class ProcessingState: State {
    func handle(context: Context) {
        print("Processing: Working on task")
        context.state = CompletedState()
    }
}

class CompletedState: State {
    func handle(context: Context) {
        print("Completed: Task finished")
    }
}

class Context {
    var state: State = ReadyState()
    
    func request() {
        state.handle(context: self)
    }
}

// Usage
let context = Context()
context.request()  // Ready: Waiting for input
context.request()  // Processing: Working on task
context.request()  // Completed: Task finished

// Order state with transitions
class OrderState {
    enum State {
        case pending, processing, shipped, delivered, cancelled
    }
    
    private(set) var currentState: State = .pending
    
    let transitions: [State: [State]] = [
        .pending: [.processing, .cancelled],
        .processing: [.shipped, .cancelled],
        .shipped: [.delivered, .returned],
        .delivered: [.returned]
    ]
    
    func transition(to newState: State) -> Bool {
        guard let allowed = transitions[currentState],
              allowed.contains(newState) else {
            print("Invalid transition from \(currentState) to \(newState)")
            return false
        }
        currentState = newState
        print("Order status changed to: \(newState)")
        return true
    }
}

let order = OrderState()
order.transition(to: .processing)
order.transition(to: .shipped)
order.transition(to: .delivered)
Coding Round
80. Proxy pattern

Proxy pattern for controlling access.

  • Subject: Real object
  • Proxy: Controls access
  • Lazy loading: Create on demand
  • Benefits: Access control, logging
swift
// Proxy pattern in Swift
protocol Subject {
    func request()
}

class RealSubject: Subject {
    func request() {
        print("RealSubject: Handling request")
    }
}

class Proxy: Subject {
    private var realSubject: RealSubject?
    
    func request() {
        if checkAccess() {
            if realSubject == nil {
                realSubject = RealSubject()
            }
            realSubject?.request()
            logAccess()
        }
    }
    
    private func checkAccess() -> Bool {
        print("Proxy: Checking access")
        return true
    }
    
    private func logAccess() {
        print("Proxy: Logging access")
    }
}

// Usage
let proxy = Proxy()
proxy.request()

// Virtual proxy (lazy loading)
class VirtualProxy: Subject {
    private var realSubject: RealSubject?
    
    func request() {
        if realSubject == nil {
            print("Proxy: Creating real subject")
            realSubject = RealSubject()
        }
        realSubject?.request()
    }
}

let virtualProxy = VirtualProxy()
virtualProxy.request()  // Creates real subject
virtualProxy.request()  // Uses existing subject

// Protection proxy
class ProtectionProxy: Subject {
    private var realSubject: RealSubject?
    private let user: String
    
    init(user: String) {
        self.user = user
    }
    
    func request() {
        if user == "admin" {
            if realSubject == nil {
                realSubject = RealSubject()
            }
            realSubject?.request()
        } else {
            print("Proxy: Access denied for user \(user)")
        }
    }
}

let protectedProxy = ProtectionProxy(user: "guest")
protectedProxy.request()
Coding Round
81. Flyweight pattern

Flyweight pattern for sharing objects.

  • Flyweight: Shared object
  • Factory: Manages flyweights
  • Benefits: Memory optimization
  • Use case: Character rendering
swift
// Flyweight pattern in Swift
class Flyweight {
    let sharedState: String
    
    init(sharedState: String) {
        self.sharedState = sharedState
    }
    
    func operation(uniqueState: String) {
        print("Shared: \(sharedState), Unique: \(uniqueState)")
    }
}

class FlyweightFactory {
    private var flyweights: [String: Flyweight] = [:]
    
    func getFlyweight(sharedState: String) -> Flyweight {
        if let flyweight = flyweights[sharedState] {
            return flyweight
        }
        let flyweight = Flyweight(sharedState: sharedState)
        flyweights[sharedState] = flyweight
        print("Creating new flyweight for: \(sharedState)")
        return flyweight
    }
}

// Usage
let factory = FlyweightFactory()
let fw1 = factory.getFlyweight(sharedState: "state1")
let fw2 = factory.getFlyweight(sharedState: "state1")
let fw3 = factory.getFlyweight(sharedState: "state2")

fw1.operation(uniqueState: "unique1")
fw2.operation(uniqueState: "unique2")
fw3.operation(uniqueState: "unique3")

// Character flyweight for text rendering
class Character {
    let char: String
    
    init(char: String) {
        self.char = char
    }
    
    func display(fontSize: Int) {
        print("Character: \(char), Size: \(fontSize)")
    }
}

class CharacterFactory {
    private var characters: [String: Character] = [:]
    
    func getCharacter(_ char: String) -> Character {
        if let character = characters[char] {
            return character
        }
        let character = Character(char: char)
        characters[char] = character
        return character
    }
}

let charFactory = CharacterFactory()
let text = "hello"
for char in text {
    let character = charFactory.getCharacter(String(char))
    character.display(fontSize: 12)
}
Coding Round
82. Bridge pattern

Bridge pattern for separating abstraction from implementation.

  • Abstraction: High-level interface
  • Implementation: Low-level operations
  • Benefits: Separation of concerns
  • Use case: Cross-platform
swift
// Bridge pattern in Swift
protocol Implementation {
    func operationImpl()
}

struct ConcreteImplementationA: Implementation {
    func operationImpl() {
        print("ConcreteImplementationA: Operation")
    }
}

struct ConcreteImplementationB: Implementation {
    func operationImpl() {
        print("ConcreteImplementationB: Operation")
    }
}

class Abstraction {
    private let impl: Implementation
    
    init(impl: Implementation) {
        self.impl = impl
    }
    
    func operation() {
        print("Abstraction: Additional logic")
        impl.operationImpl()
    }
}

// Usage
let implA = ConcreteImplementationA()
let implB = ConcreteImplementationB()
let abstraction1 = Abstraction(impl: implA)
let abstraction2 = Abstraction(impl: implB)

abstraction1.operation()
abstraction2.operation()

// Extended abstraction
class ExtendedAbstraction: Abstraction {
    override func operation() {
        print("ExtendedAbstraction: More logic")
        super.operation()
    }
}

let extended = ExtendedAbstraction(impl: implA)
extended.operation()
Coding Round
83. Adapter pattern

Adapter pattern for converting interfaces.

  • Target: Expected interface
  • Adaptee: Existing interface
  • Adapter: Bridges interfaces
  • Benefits: Reusability
swift
// Adapter pattern in Swift
protocol Target {
    func request()
}

struct TargetImpl: Target {
    func request() {
        print("Target: Request")
    }
}

struct Adaptee {
    func specificRequest() {
        print("Adaptee: Specific Request")
    }
}

struct Adapter: Target {
    private let adaptee: Adaptee
    
    init(adaptee: Adaptee) {
        self.adaptee = adaptee
    }
    
    func request() {
        adaptee.specificRequest()
    }
}

// Usage
let adaptee = Adaptee()
let adapter = Adapter(adaptee: adaptee)
adapter.request()

// Object adapter (using composition)
class ObjectAdapter: Target {
    private let adaptee: Adaptee
    
    init(adaptee: Adaptee) {
        self.adaptee = adaptee
    }
    
    func request() {
        adaptee.specificRequest()
    }
}

// Adapter for incompatible interfaces
struct OldSystem {
    func oldMethod() -> String {
        return "Old system data"
    }
}

struct NewSystem {
    func newMethod() -> String {
        return "New system data"
    }
}

struct SystemAdapter {
    private let system: Any
    
    init(system: Any) {
        self.system = system
    }
    
    func getData() -> String? {
        if let old = system as? OldSystem {
            return old.oldMethod()
        } else if let new = system as? NewSystem {
            return new.newMethod()
        }
        return nil
    }
}

let oldSystem = OldSystem()
let adapter2 = SystemAdapter(system: oldSystem)
print(adapter2.getData() ?? "nil")
Coding Round
84. Facade pattern

Facade pattern for simplifying subsystems.

  • Facade: Simplified interface
  • Subsystem: Complex components
  • Benefits: Simplified interface
  • Use case: Library APIs
swift
// Facade pattern in Swift
class SubsystemA {
    func operationA() {
        print("SubsystemA: Operation")
    }
}

class SubsystemB {
    func operationB() {
        print("SubsystemB: Operation")
    }
}

class SubsystemC {
    func operationC() {
        print("SubsystemC: Operation")
    }
}

class Facade {
    private let subsystemA = SubsystemA()
    private let subsystemB = SubsystemB()
    private let subsystemC = SubsystemC()
    
    func operation() {
        print("Facade: Complex operation")
        subsystemA.operationA()
        subsystemB.operationB()
        subsystemC.operationC()
    }
    
    func simplifiedOperation() {
        print("Facade: Simplified operation")
        subsystemA.operationA()
    }
}

// Usage
let facade = Facade()
facade.operation()
facade.simplifiedOperation()

// Database facade
class DatabaseFacade {
    private var connection: String?
    
    func connect() {
        print("Connecting to database")
        connection = "Connected"
    }
    
    func query(_ sql: String) -> String? {
        guard connection != nil else { return nil }
        print("Executing: \(sql)")
        return "Query results"
    }
    
    func disconnect() {
        print("Disconnecting")
        connection = nil
    }
}

let db = DatabaseFacade()
db.connect()
let result = db.query("SELECT * FROM users")
db.disconnect()
Coding Round
85. Composite pattern

Composite pattern for tree structures.

  • Component: Interface for all
  • Leaf: Individual object
  • Composite: Container
  • Benefits: Uniform interface
swift
// Composite pattern in Swift
protocol Component {
    func operation()
}

struct Leaf: Component {
    let name: String
    
    func operation() {
        print("Leaf \(name): Operation")
    }
}

class Composite: Component {
    let name: String
    private var children: [Component] = []
    
    init(name: String) {
        self.name = name
    }
    
    func add(_ component: Component) {
        children.append(component)
    }
    
    func remove(_ component: Component) {
        children.removeAll { $0 as AnyObject === component as AnyObject }
    }
    
    func operation() {
        print("Composite \(name): Operation")
        children.forEach { $0.operation() }
    }
}

// Usage
let leaf1 = Leaf(name: "A")
let leaf2 = Leaf(name: "B")
let composite = Composite(name: "Root")
composite.add(leaf1)
composite.add(leaf2)
composite.operation()

// File system example
protocol FileSystemComponent {
    func getSize() -> Int
    func display(indent: String)
}

class File: FileSystemComponent {
    let name: String
    let size: Int
    
    init(name: String, size: Int) {
        self.name = name
        self.size = size
    }
    
    func getSize() -> Int {
        return size
    }
    
    func display(indent: String = "") {
        print("\(indent)📄 \(name) (\(size) bytes)")
    }
}

class Directory: FileSystemComponent {
    let name: String
    private var children: [FileSystemComponent] = []
    
    init(name: String) {
        self.name = name
    }
    
    func add(_ component: FileSystemComponent) {
        children.append(component)
    }
    
    func getSize() -> Int {
        return children.reduce(0) { $0 + $1.getSize() }
    }
    
    func display(indent: String = "") {
        print("\(indent)📁 \(name) (\(getSize()) bytes)")
        children.forEach { $0.display(indent: indent + "  ") }
    }
}

let root = Directory(name: "Root")
let file1 = File(name: "file1.txt", size: 100)
let file2 = File(name: "file2.txt", size: 200)
let subDir = Directory(name: "SubDir")
subDir.add(File(name: "file3.txt", size: 300))

root.add(file1)
root.add(file2)
root.add(subDir)
root.display()
Coding Round
86. Visitor pattern

Visitor pattern for adding operations without modifying elements.

  • Visitor: Defines operations
  • Element: Accepts visitors
  • Benefits: Adding operations without modifying
  • Use case: Compilers, AST
swift
// Visitor pattern in Swift
protocol Visitor {
    func visit(elementA: ElementA)
    func visit(elementB: ElementB)
}

protocol Element {
    func accept(_ visitor: Visitor)
}

struct ElementA: Element {
    let data: String
    
    func accept(_ visitor: Visitor) {
        visitor.visit(elementA: self)
    }
}

struct ElementB: Element {
    let data: String
    
    func accept(_ visitor: Visitor) {
        visitor.visit(elementB: self)
    }
}

struct ConcreteVisitor: Visitor {
    func visit(elementA: ElementA) {
        print("Visiting ElementA with data: \(elementA.data)")
    }
    
    func visit(elementB: ElementB) {
        print("Visiting ElementB with data: \(elementB.data)")
    }
}

// Usage
let visitor = ConcreteVisitor()
let elementA = ElementA(data: "A data")
let elementB = ElementB(data: "B data")

elementA.accept(visitor)
elementB.accept(visitor)

// Visitor with multiple operations
protocol OperationVisitor {
    func visit(elementA: ElementA) -> String
    func visit(elementB: ElementB) -> String
}

struct PrintVisitor: OperationVisitor {
    func visit(elementA: ElementA) -> String {
        return "Print: ElementA - \(elementA.data)"
    }
    
    func visit(elementB: ElementB) -> String {
        return "Print: ElementB - \(elementB.data)"
    }
}

struct CountVisitor: OperationVisitor {
    var count = 0
    
    mutating func visit(elementA: ElementA) -> String {
        count += 1
        return "ElementA counted"
    }
    
    mutating func visit(elementB: ElementB) -> String {
        count += 1
        return "ElementB counted"
    }
}

let elements: [Element] = [ElementA(data: "A1"), ElementB(data: "B1"), ElementA(data: "A2")]
var printVisitor = PrintVisitor()
var countVisitor = CountVisitor()

for element in elements {
    if let a = element as? ElementA {
        print(printVisitor.visit(elementA: a))
        _ = countVisitor.visit(elementA: a)
    } else if let b = element as? ElementB {
        print(printVisitor.visit(elementB: b))
        _ = countVisitor.visit(elementB: b)
    }
}
print("Total elements: \(countVisitor.count)")
Coding Round
87. Iterator pattern

Iterator pattern for sequential access.

  • Iterator: Traverses collection
  • Aggregate: Creates iterator
  • Benefits: Uniform traversal
  • Use case: Collection traversal
swift
// Iterator pattern in Swift
struct CustomIterator<T>: IteratorProtocol {
    private let collection: [T]
    private var index = 0
    
    init(collection: [T]) {
        self.collection = collection
    }
    
    mutating func next() -> T? {
        guard index < collection.count else { return nil }
        let element = collection[index]
        index += 1
        return element
    }
}

struct CustomCollection<T>: Sequence {
    private let items: [T]
    
    init(_ items: [T]) {
        self.items = items
    }
    
    func makeIterator() -> CustomIterator<T> {
        return CustomIterator(collection: items)
    }
}

// Usage
let collection = CustomCollection(["A", "B", "C"])
for item in collection {
    print(item)
}

// Fibonacci iterator
struct FibonacciIterator: IteratorProtocol {
    var a = 0
    var b = 1
    
    mutating func next() -> Int? {
        let value = a
        let temp = a + b
        a = b
        b = temp
        return value
    }
}

struct FibonacciSequence: Sequence {
    let count: Int
    
    func makeIterator() -> FibonacciIterator {
        return FibonacciIterator()
    }
}

for num in FibonacciSequence(count: 10).prefix(10) {
    print(num)
}

// Step iterator
struct StepIterator<T>: IteratorProtocol {
    private let collection: [T]
    private let step: Int
    private var index = 0
    
    init(collection: [T], step: Int) {
        self.collection = collection
        self.step = step
    }
    
    mutating func next() -> T? {
        guard index < collection.count else { return nil }
        let element = collection[index]
        index += step
        return element
    }
}

let stepIterator = StepIterator(collection: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], step: 2)
while let value = stepIterator.next() {
    print(value)  // 1, 3, 5, 7, 9
}
Coding Round
88. Template Method pattern

Template Method for algorithm skeletons.

  • AbstractClass: Defines template
  • ConcreteClass: Implements steps
  • Benefits: Code reuse
  • Use case: Frameworks
swift
// Template Method pattern in Swift
class AbstractClass {
    func templateMethod() {
        step1()
        step2()
        step3()
    }
    
    func step1() {
        print("Step 1")
    }
    
    func step2() {
        // Abstract - to be overridden
    }
    
    func step3() {
        print("Step 3")
    }
}

class ConcreteClass: AbstractClass {
    override func step2() {
        print("Concrete Step 2")
    }
}

// Usage
let concrete = ConcreteClass()
concrete.templateMethod()

// Data processor template
class DataProcessor {
    func process(_ data: [String: Any]) {
        validate(data)
        transform(data)
        save(data)
        notify(data)
    }
    
    func validate(_ data: [String: Any]) {
        if data.isEmpty {
            print("Data is empty")
        }
        print("Data validated")
    }
    
    func transform(_ data: [String: Any]) {
        // Abstract - to be overridden
    }
    
    func save(_ data: [String: Any]) {
        print("Data saved: \(data)")
    }
    
    func notify(_ data: [String: Any]) {
        print("Notification sent")
    }
}

class JSONProcessor: DataProcessor {
    override func transform(_ data: [String: Any]) {
        print("Transforming JSON: \(data)")
    }
}

class XMLProcessor: DataProcessor {
    override func transform(_ data: [String: Any]) {
        print("Transforming XML: \(data)")
    }
}

let jsonProcessor = JSONProcessor()
jsonProcessor.process(["name": "Alice"])

let xmlProcessor = XMLProcessor()
xmlProcessor.process(["name": "Bob"])
Coding Round
89. Builder pattern

Builder pattern for constructing complex objects.

  • Builder: Constructs parts
  • Director: Orchestrates construction
  • Product: Constructed object
  • Benefits: Step-by-step construction
swift
// Builder pattern in Swift
class Product {
    private var parts: [String] = []
    
    func add(_ part: String) {
        parts.append(part)
    }
    
    func listParts() {
        print(parts.joined(separator: ", "))
    }
}

class Builder {
    private var product = Product()
    
    func reset() {
        product = Product()
    }
    
    func buildStepA() {
        product.add("Part A")
    }
    
    func buildStepB() {
        product.add("Part B")
    }
    
    func getResult() -> Product {
        return product
    }
}

class Director {
    private let builder: Builder
    
    init(builder: Builder) {
        self.builder = builder
    }
    
    func buildMinimal() {
        builder.buildStepA()
    }
    
    func buildFull() {
        builder.buildStepA()
        builder.buildStepB()
    }
}

// Usage
let builder = Builder()
let director = Director(builder: builder)
director.buildMinimal()
let product = builder.getResult()
product.listParts()  // Part A

// Fluent builder
class FluentBuilder {
    private var product: [String: Any] = [:]
    
    func name(_ name: String) -> FluentBuilder {
        product["name"] = name
        return self
    }
    
    func age(_ age: Int) -> FluentBuilder {
        product["age"] = age
        return self
    }
    
    func email(_ email: String) -> FluentBuilder {
        product["email"] = email
        return self
    }
    
    func build() -> [String: Any] {
        return product
    }
}

let user = FluentBuilder()
    .name("Alice")
    .age(25)
    .email("alice@example.com")
    .build()

print(user)
Coding Round
90. Prototype pattern

Prototype pattern for cloning objects.

  • Prototype: Cloneable object
  • Clone: Creates a copy
  • Deep copy: Recursive copy
  • Benefits: Object reuse, performance
swift
// Prototype pattern in Swift
class Prototype: NSCopying {
    var name: String
    var nested: [String: Any]
    
    init(name: String, nested: [String: Any]) {
        self.name = name
        self.nested = nested
    }
    
    func copy(with zone: NSZone? = nil) -> Any {
        return Prototype(name: name, nested: nested)
    }
    
    func deepCopy() -> Prototype {
        let nestedCopy = nested.mapValues { value in
            if let dict = value as? [String: Any] {
                return dict
            } else if let array = value as? [Any] {
                return array
            }
            return value
        }
        return Prototype(name: name, nested: nestedCopy)
    }
}

// Usage
let original = Prototype(name: "Original", nested: ["value": 42])
let copy = original.copy() as! Prototype
copy.name = "Copy"
copy.nested["value"] = 99

print(original.name)  // Original
print(original.nested["value"] ?? 0)  // 42 (shallow copy)

let deepCopy = original.deepCopy()
deepCopy.nested["value"] = 100
print(original.nested["value"] ?? 0)  // 42 (deep copy)

// Using Codable for deep copy
struct CodablePrototype: Codable {
    var name: String
    var nested: [String: Int]
    
    func deepCopy() throws -> CodablePrototype {
        let encoder = JSONEncoder()
        let data = try encoder.encode(self)
        let decoder = JSONDecoder()
        return try decoder.decode(CodablePrototype.self, from: data)
    }
}

let codableOriginal = CodablePrototype(name: "Original", nested: ["value": 42])
let codableCopy = try? codableOriginal.deepCopy()
codableCopy?.name = "Copy"
codableCopy?.nested["value"] = 99

print(codableOriginal.name)  // Original
Coding Round
91. Error Handling with Result type

Error handling using Result type for success/failure.

  • Result type: Result<Success, Failure>
  • Success: .success(value)
  • Failure: .failure(error)
  • Switch: Handle both cases
swift
// Error Handling with Result type
enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingError
}

func fetchUser(id: Int) -> Result<User, NetworkError> {
    // Simulate API call
    guard id > 0 else { return .failure(.invalidURL) }
    // Simulate success
    let user = User(id: id, name: "Alice", email: "alice@example.com")
    return .success(user)
}

// Usage
let result = fetchUser(id: 1)
switch result {
case .success(let user):
    print("User: \(user.name)")
case .failure(let error):
    print("Error: \(error)")
}
Coding Round
92. JSON Encoding and Decoding

JSON serialization using Codable and JSONEncoder.

  • Codable: struct Person: Codable
  • Encoder: JSONEncoder().encode(person)
  • Decoder: JSONDecoder().decode(Person.self, from: data)
  • Error handling: try-catch
swift
// JSON Encoding and Decoding
struct Person: Codable {
    let name: String
    let age: Int
    let email: String
}

func encodePerson(_ person: Person) -> String? {
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    guard let data = try? encoder.encode(person) else { return nil }
    return String(data: data, encoding: .utf8)
}

func decodePerson(_ json: String) -> Person? {
    guard let data = json.data(using: .utf8) else { return nil }
    let decoder = JSONDecoder()
    return try? decoder.decode(Person.self, from: data)
}

// Usage
let person = Person(name: "Alice", age: 25, email: "alice@example.com")
let json = encodePerson(person)
print(json ?? "")

let decoded = decodePerson(json ?? "")
print(decoded ?? person)
Coding Round
93. Concurrency with DispatchQueue

Concurrency using DispatchQueue for async tasks.

  • Serial queue: DispatchQueue(label: "serial")
  • Concurrent queue: .attributes: .concurrent
  • Main queue: DispatchQueue.main.async
  • Barrier: .async(flags: .barrier)
swift
// Concurrency with DispatchQueue
import Foundation

// Serial queue
let serialQueue = DispatchQueue(label: "com.example.serial")

serialQueue.async {
    print("Task 1")
    Thread.sleep(forTimeInterval: 0.5)
}

serialQueue.async {
    print("Task 2")
}

// Concurrent queue
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)

concurrentQueue.async {
    print("Concurrent Task 1")
    Thread.sleep(forTimeInterval: 0.5)
}

concurrentQueue.async {
    print("Concurrent Task 2")
}

// Main queue
DispatchQueue.main.async {
    print("Main queue task")
}

// Barrier
concurrentQueue.async(flags: .barrier) {
    print("Barrier task")
}
Coding Round
94. Async/Await with Task

Asynchronous programming using async/await and Task.

  • async functions: func fetch() async -> String
  • await: let result = await fetch()
  • Task: Task { }
  • Parallel: async let
swift
// Async/Await with Task
import Foundation

func fetchUser(id: Int) async throws -> User {
    try await Task.sleep(nanoseconds: 1_000_000_000)
    return User(id: id, name: "Alice", email: "alice@example.com")
}

func fetchPosts(userId: Int) async throws -> [String] {
    try await Task.sleep(nanoseconds: 500_000_000)
    return ["Post 1", "Post 2"]
}

func fetchUserData() async {
    do {
        async let user = fetchUser(id: 1)
        async let posts = fetchPosts(userId: 1)
        let (userData, userPosts) = try await (user, posts)
        print("User: \(userData.name)")
        print("Posts: \(userPosts)")
    } catch {
        print("Error: \(error)")
    }
}

Task {
    await fetchUserData()
}
Coding Round
95. Testing with XCTest

Unit testing using XCTest framework.

  • Test class: class MyTests: XCTestCase
  • setUp/tearDown: Setup and cleanup
  • Assertions: XCTAssertEqual, XCTAssertThrowsError
  • Async tests: func testAsync() async
swift
// Testing with XCTest
import XCTest

class CalculatorTests: XCTestCase {
    var calculator: Calculator!
    
    override func setUp() {
        super.setUp()
        calculator = Calculator()
    }
    
    override func tearDown() {
        calculator = nil
        super.tearDown()
    }
    
    func testAdd() {
        XCTAssertEqual(calculator.add(2, 3), 5)
        XCTAssertEqual(calculator.add(-1, 1), 0)
    }
    
    func testDivide() {
        XCTAssertEqual(try? calculator.divide(10, 2), 5)
        XCTAssertThrowsError(try calculator.divide(10, 0))
    }
    
    func testAsyncOperation() async {
        let result = await calculator.asyncAdd(2, 3)
        XCTAssertEqual(result, 5)
    }
}

class Calculator {
    func add(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
    
    func divide(_ a: Int, _ b: Int) throws -> Int {
        guard b != 0 else {
            throw NSError(domain: "DivideError", code: 1)
        }
        return a / b
    }
    
    func asyncAdd(_ a: Int, _ b: Int) async -> Int {
        try? await Task.sleep(nanoseconds: 100_000_000)
        return a + b
    }
}
Coding Round
96. Closures and Capture Lists

Closures with capture lists for memory management.

  • Capture list: [weak self]
  • Unowned: [unowned self]
  • Escaping: @escaping
  • Memory: Avoid retain cycles
swift
// Closures and Capture Lists
class NetworkManager {
    var data: String?
    
    func fetchData(completion: @escaping () -> Void) {
        DispatchQueue.global().async { [weak self] in
            Thread.sleep(forTimeInterval: 0.5)
            self?.data = "Data loaded"
            DispatchQueue.main.async {
                completion()
            }
        }
    }
    
    // Unowned capture
    func processData() {
        fetchData { [unowned self] in
            print(self.data ?? "nil")
        }
    }
}

// Usage
let manager = NetworkManager()
manager.processData()

// Closure with capture list
var counter = 0
let increment = { [counter] in
    print(counter)  // Captures value at creation
}
counter = 10
increment()  // Prints 0
Coding Round
97. Property Wrappers

Property wrappers for reusable property logic.

  • Definition: @propertyWrapper struct Capitalized
  • wrappedValue: var wrappedValue: Type
  • Usage: @Capitalized var name: String
  • Parameters: init(wrappedValue: Type, ...)
swift
// Property Wrappers
@propertyWrapper
struct Capitalized {
    private var value: String = ""
    
    var wrappedValue: String {
        get { value }
        set { value = newValue.capitalized }
    }
    
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

@propertyWrapper
struct MinMax {
    private var value: Int
    let min: Int
    let max: Int
    
    init(wrappedValue: Int, min: Int, max: Int) {
        self.min = min
        self.max = max
        self.value = min(max(wrappedValue, min), max)
    }
    
    var wrappedValue: Int {
        get { value }
        set { value = min(max(newValue, min), max) }
    }
}

struct User {
    @Capitalized var name: String
    @MinMax(min: 0, max: 150) var age: Int
}

var user = User(name: "alice", age: 25)
print(user.name)  // Alice
user.age = 200
print(user.age)  // 150
Coding Round
98. Result Builders

Result builders for declarative DSL construction.

  • @resultBuilder: Define builder
  • buildBlock: Combine components
  • buildEither: Conditional components
  • Usage: @ArrayBuilder
swift
// Result Builders
@resultBuilder
struct ArrayBuilder<T> {
    static func buildBlock(_ components: T...) -> [T] {
        return components
    }
}

func buildArray<T>(@ArrayBuilder<T> _ content: () -> [T]) -> [T] {
    return content()
}

// Usage
let numbers = buildArray {
    1
    2
    3
    4
    5
}
print(numbers)  // [1, 2, 3, 4, 5]

// Conditional items
@resultBuilder
struct ConditionalBuilder<T> {
    static func buildBlock(_ components: T...) -> [T] {
        return components
    }
    
    static func buildEither(first: T) -> T {
        return first
    }
    
    static func buildEither(second: T) -> T {
        return second
    }
}

func buildConditional<T>(_ condition: Bool, @ConditionalBuilder<T> _ content: () -> T) -> T {
    return content()
}

let value = buildConditional(true) {
    "Hello"
}
print(value)  // Hello
Coding Round
99. AsyncSequence and AsyncStream

Async sequences for streaming asynchronous data.

  • AsyncSequence: protocol AsyncSequence
  • AsyncIterator: mutating func next() async
  • AsyncStream: AsyncStream { continuation in }
  • Iteration: for await
swift
// AsyncSequence and AsyncStream
import Foundation

struct NumberGenerator: AsyncSequence {
    typealias Element = Int
    let max: Int
    
    func makeAsyncIterator() -> AsyncIterator {
        return AsyncIterator(max: max)
    }
    
    struct AsyncIterator: AsyncIteratorProtocol {
        var current = 0
        let max: Int
        
        mutating func next() async -> Int? {
            current += 1
            if current > max {
                return nil
            }
            try? await Task.sleep(nanoseconds: 100_000_000)
            return current
        }
    }
}

// Usage
Task {
    for await num in NumberGenerator(max: 5) {
        print(num)
    }
}

// AsyncStream
func createAsyncStream() -> AsyncStream<String> {
    return AsyncStream { continuation in
        Task {
            for i in 1...5 {
                try? await Task.sleep(nanoseconds: 100_000_000)
                continuation.yield("Item \(i)")
            }
            continuation.finish()
        }
    }
}

Task {
    for await item in createAsyncStream() {
        print(item)
    }
}
Coding Round
100. Swift Best Practices

Best practices for writing clean, efficient Swift code.

  • Guard: Early returns with guard
  • Extensions: Organize code
  • Type inference: Let Swift infer types
  • Optionals: Use optional binding
  • Enums: Use enums for states
swift
// Swift Best Practices
// 1. Use guard for early returns
func processUser(_ user: User?) -> String {
    guard let user = user else { return "No user" }
    guard !user.name.isEmpty else { return "Empty name" }
    return "Hello, \(user.name)"
}

// 2. Use extensions for organization
extension String {
    func isValidEmail() -> Bool {
        return contains("@") && contains(".")
    }
}

// 3. Use type inference
let name = "Alice"  // String inferred
let age = 25  // Int inferred

// 4. Use optionals appropriately
let optionalValue: String? = "Hello"
if let unwrapped = optionalValue {
    print(unwrapped)
}

// 5. Use enums for states
enum ResultState {
    case success(data: String)
    case error(message: String)
    case loading
}

// 6. Use protocols for abstraction
protocol DataService {
    func fetchData() -> String
}

// 7. Use value types (structs) when possible
struct UserData {
    let id: Int
    let name: String
}

// 8. Use computed properties
struct Circle {
    var radius: Double
    var area: Double {
        return Double.pi * radius * radius
    }
}

// 9. Use lazy properties for expensive initialization
class DataManager {
    lazy var expensiveData: String = {
        // Expensive computation
        return "Data"
    }()
}

// 10. Use weak references to avoid retain cycles
class Parent {
    weak var child: Child?
}

class Child {
    var parent: Parent?
}