Swift Interview Questions
41 questions with detailed answers
Question:
What is Swift and what are its key features?
Answer:
Swift is a powerful and intuitive programming language developed by Apple for iOS, macOS, watchOS, and tvOS app development.\n\n• **Key Features:**\n• Modern syntax that is concise and expressive\n• Type safety and memory safety\n• Fast performance with LLVM compiler\n• Interoperability with Objective-C\n• Automatic Reference Counting (ARC)\n• Optionals for handling nil values safely\n• Generics for writing flexible, reusable code\n• Protocol-oriented programming\n• Playgrounds for interactive development\n• Open source with active community support\n\n**Example:**\n\nlet greeting = "Hello, Swift!"\nprint(greeting)\n
Question:
Explain the difference between var and let in Swift.
Answer:
The difference var let relates to mutability in Swift.\n\n• **var (Variable):**\n• Creates a mutable variable\n• Value can be changed after declaration\n• Used when you need to modify the value\n\n• **let (Constant):**\n• Creates an immutable constant\n• Value cannot be changed after initialization\n• Preferred for values that won't change\n• Better performance and safety\n\n**Examples:**\n\nvar age = 25\nage = 26 // ✅ Valid - can change\n\nlet name = "John"\n// name = "Jane" // ❌ Error - cannot change\n\nlet numbers = [1, 2, 3]\nnumbers.append(4) // ✅ Valid - array content can change\n
Question:
What are optionals in Swift and why are they important?
Answer:
Optionals are a fundamental Swift feature that represents values that might be absent (nil).\n\n• **Purpose:**\n• Handle absence of values safely\n• Prevent null pointer exceptions\n• Make code more explicit about potential nil values\n• Compile-time safety for nil handling\n\n• **Declaration:**\n\nvar optionalString: String? = "Hello"\nvar optionalInt: Int? = nil\n\n\n• **Unwrapping Methods:**\n\n// Force unwrapping (use carefully)\nlet value = optionalString!\n\n// Optional binding\ let unwrapped = optionalString {\n print(unwrapped)\n}\n\n// Nil coalescing\nlet result = optionalString ?? "Default"\n
Question:
What are the basic data types in Swift?
Answer:
Swift provides several fundamental data types for different kinds of values.\n\n• **Numeric Types:**\n• Int - Integer values (32-bit or 64-bit)\n• Double - 64-bit floating-point numbers\n• Float - 32-bit floating-point numbers\n• UInt - Unsigned integers\n\n• **Text Types:**\n• String - Text data with Unicode support\n• Character - Single Unicode character\n\n• **Boolean Type:**\n• Bool - true or false values\n\n• **Collection Types:**\n• Array - Ordered collection of values\n• Set - Unordered collection of unique values\n• Dictionary - Key-value pairs\n\n• **Optional Types:**\n• Optional - Values that can be nil\n\n**Examples:**\n\nlet age: Int = 25\nlet price: Double = 99.99\nlet name: String = "Swift"\nlet isActive: Bool = true\nlet numbers: [Int] = [1, 2, 3]\nlet optionalValue: String? = nil\n
Question:
What is Swift and what are its key features?
Answer:
Swift is a powerful programming language developed by Apple for iOS, macOS, watchOS, and tvOS development. Key features: 1) Type safety - prevents type-related errors, 2) Optionals - handle absence of values safely, 3) Automatic Reference Counting (ARC) - memory management, 4) Closures - self-contained blocks of functionality, 5) Generics - write flexible, reusable code, 6) Protocol-oriented programming, 7) Fast performance, 8) Modern syntax.
Question:
Explain the difference between classes and structures in Swift.
Answer:
Classes and structures are fundamental building blocks in Swift with key differences.\n\n• **Classes (Reference Types):**\n• Passed by reference\n• Support inheritance\n• Can have deinitializers\n• Reference counting applies\n• Identity operators (=== and !==)\n• Can be changed even when declared with let\n\n• **Structures (Value Types):**\n• Passed by value (copied)\n• No inheritance support\n• No deinitializers\n• Automatic memberwise initializers\n• Cannot be changed when declared with let\n• Copy-on-write optimization\n\n**Examples:**\n\nclass PersonClass {
\n var name: String\n init(name: String) { self.name = name }\n}\n\nstruct PersonStruct {
\n var name: String\n}\n\nlet classInstance = PersonClass(name: "John")\nclassInstance.name = "Jane" // ✅ Allowed\n\nlet structInstance = PersonStruct(name: "John")\n// structInstance.name = "Jane" // ❌ Error\n
Question:
What is ARC (Automatic Reference Counting) and how does it work?
Answer:
ARC is Swift's memory management system that automatically tracks and manages memory usage.\n\n• **How ARC Works:**\n• Tracks number of references to each class instance\n• Automatically deallocates instances when reference count reaches zero\n• Works at compile time, not runtime\n• No performance overhead during execution\n\n• **Reference Types:**\n• **Strong:** Default reference type, keeps object alive\n• **Weak:** Doesn't keep object alive, becomes nil when deallocated\n• **Unowned:** Doesn't keep object alive, assumes object exists\n\n• **Retain Cycles:**\n\nclass Person {
\n var apartment: Apartment?\n}\n\nclass Apartment {
\n let tenant: Person\n init(tenant: Person) {\n self.tenant = tenant\n }\n}\n\n\n• **Best Practices:**\n• Use weak for delegate patterns\n• Use unowned when you're certain the reference won't be nil\n• Avoid strong reference cycles
Question:
Explain protocols and protocol-oriented programming in Swift.
Answer:
Protocols define blueprints of methods, properties, and requirements that types can adopt.\n\n• **Protocol Basics:**\n• Define requirements without implementation\n• Can be adopted by classes, structs, and enums\n• Support inheritance and composition\n• Enable polymorphism and abstraction\n\n\nprotocol Drawable {\n var area: Double { get }\n func draw()\n}\n\nstruct Circle: Drawable {\n let radius: Double\n \n var area: Double {\n return Double.pi * radius * radius\n }\n \n func draw() {\n print("Drawing a circle")\n }\n}\n\n\n• **Protocol Extensions:**\n• Provide default implementations\n• Add functionality to existing types\n• Enable protocol-oriented programming\n\n\nextension Drawable {\n func describe() {\n print("Area: \(area)")\n }\n}\n\n\n• **Associated Types:**\n\nprotocol Container {\n associatedtype Item\n func addItem(_ item: Item)\n}\n
Question:
Explain optionals in Swift with examples.
Answer:
Optionals represent values that might be absent. Declaration: var name: String? = nil. Unwrapping methods: 1) Force unwrapping: name! (crashes if nil), 2) Optional binding: if let safeName = name { }, 3) Nil coalescing: name ?? "Default", 4) Optional chaining: person?.address?.street. Optionals prevent runtime crashes by making nil handling explicit and safe.
Question:
What are closures in Swift and how are they used?
Answer:
Closures are self-contained blocks of functionality that can be passed around and used in code.\n\n• **Closure Syntax:**\n\n{ (parameters) -> ReturnType in\n statements\n}\n\n\n• **Common Uses:**\n• Higher-order functions (map, filter, reduce)\n• Completion handlers\n• Event handling\n• Asynchronous operations\n\n• **Examples:**\n\n// Basic closure\nlet greeting = { (name: String) -> String in\n return "Hello, \(name)!"\n}\n\n// Array operations\nlet numbers = [1, 2, 3, 4, 5]\nlet doubled = numbers.map { $0 * 2 }\nlet evens = numbers.filter { $0 % 2 == 0 }\nlet sum = numbers.reduce(0, +)\n\n// Trailing closure syntax\nUIView.animate(withDuration: 0.3) {\n view.alpha = 0.5\n}\n\n\n• **Capturing Values:**\n• Closures can capture and store references\n• Automatic memory management with ARC\n• Use weak/unowned to prevent retain cycles\n\n• **Escaping Closures:**\n• @escaping for closures that outlive function\n• Common in asynchronous operations
Question:
Explain error handling in Swift.
Answer:
Swift provides robust error handling using throwing functions and do-catch statements.\n\n• **Error Protocol:**\n\nenum NetworkError: Error {\n case invalidURL\n case noData\n case decodingFailed\n}\n\n\n• **Throwing Functions:**\n\nfunc fetchData(from url: String) throws -> Data {\n let validURL = URL(string: url) else {\n throw NetworkError.invalidURL\n }\n \n // Simulate network call\n let data = simulateNetworkCall(validURL) else {\n throw NetworkError.noData\n }\n \n return data\n}\n\n\n• **Error Handling:**\n\ndo {\n let data = try fetchData(from: "https://api.example.com")\n print("Success: \(data)")\n} catch NetworkError.invalidURL {\n print("Invalid URL provided")\n} catch NetworkError.noData {\n print("No data received")\n} catch {\n print("Unknown error: \(error)")\n}\n\n\n• **Optional Try:**\n\nlet data = try? fetchData(from: url) // Returns nil on error\nlet data = try! fetchData(from: url) // Crashes on error\n
Question:
What are generics in Swift and why are they useful?
Answer:
Generics enable writing flexible, reusable code that works with any type while maintaining type safety.\n\n• **Generic Functions:**\n\nfunc swapValues(_ a: inout T, _ b: inout T) {\n let temp = a\n a = b\n b = temp\n}\n\nvar x = 5, y = 10\nswapValues(&x, &y) // Works with Int\n\nvar str1 = "Hello", str2 = "World"\nswapValues(&str1, &str2) // Works with String\n\n\n• **Generic Types:**\n\nstruct Stack {\n var items: [Element] = []\n \n func push(_ item: Element) {\n items.append(item)\n }\n \n func pop() -> Element? {\n return items.popLast()\n }\n}\n\nvar intStack = Stack()\nvar stringStack = Stack()\n\n\n• **Type Constraints:**\n\nfunc findIndex(of valueToFind: T, in array: [T]) -> Int? {\n for (index, value) in array.enumerated() {\n if value == valueToFind {\n return index\n }\n }\n return nil\n}\n\n\n• **Benefits:**\n• Code reusability\n• Type safety\n• Performance optimization\n• Reduced code duplication
Question:
Explain property observers in Swift.
Answer:
Property observers monitor changes to a property's value and respond accordingly.\n\n• **Types of Observers:**\n• **willSet:** Called before value is stored\n• **didSet:** Called after value is stored\n\n\nclass StepCounter {
\n var totalSteps: Int = 0 {\n willSet(newTotalSteps) {\n print("About to set totalSteps to \(newTotalSteps)")\n }\n didSet {\n if totalSteps > oldValue {\n print("Added \(totalSteps - oldValue) steps")\n }\n }\n }\n}\n\nlet stepCounter = StepCounter()\nstepCounter.totalSteps = 200\n// About to set totalSteps to 200\n// Added 200 steps\n\n\n• **Use Cases:**\n• Validation before setting values\n• Triggering UI updates\n• Logging changes\n• Maintaining data consistency\n• Synchronizing related properties\n\n• **Important Notes:**\n• Cannot be used with lazy properties\n• Not called during initialization\n• Available for stored properties only\n• Can access oldValue in didSet\n• Can access newValue in willSet
Question:
What is the difference between map, flatMap, and compactMap?
Answer:
These are higher-order functions for transforming collections with different behaviors.\n\n• **map:**\n• Transforms each element using a closure\n• Returns array of same size\n• One-to-one transformation\n\n\nlet numbers = [1, 2, 3, 4]\nlet doubled = numbers.map { $0 * 2 }\n// Result: [2, 4, 6, 8]\n\n\n• **compactMap:**\n• Transforms and removes nil values\n• Returns array with non-nil results\n• Filters out optionals\n\n\nlet strings = ["1", "2", "abc", "4"]\nlet numbers = strings.compactMap { Int($0) }\n// Result: [1, 2, 4]\n\n\n• **flatMap:**\n• Transforms and flattens nested collections\n• Removes one level of nesting\n• Useful for nested arrays\n\n\nlet nestedArrays = [[1, 2], [3, 4], [5, 6]]\nlet flattened = nestedArrays.flatMap { $0 }\n// Result: [1, 2, 3, 4, 5, 6]\n\n// With transformation\nlet words = ["hello", "world"]\nlet characters = words.flatMap { $0 }\n// Result: ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]\n\n\n• **Key Differences:**\n• map: 1:1 transformation\n• compactMap: 1:0 or 1:1 (removes nils)\n• flatMap: 1:many (flattens collections)
Question:
What is method swizzling in Swift and when would you use it?
Answer:
Method swizzling allows changing method implementations at runtime, primarily used for debugging and testing.\n\n• **Implementation:**\n\nimport ObjectiveC\n\nextension UIViewController {\n @ func swizzled_viewDidLoad() {\n print("View loaded")\n swizzled_viewDidLoad() // Calls original\n }\n \n func swizzleViewDidLoad() {\n let originalSelector = #selector(viewDidLoad)\n let swizzledSelector = #selector(swizzled_viewDidLoad)\n \n let originalMethod = class_getInstanceMethod(self, originalSelector),\n let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) else {\n return\n }\n \n method_exchangeImplementations(originalMethod, swizzledMethod)\n }\n}\n\n\n• **Use Cases:**\n• Analytics tracking\n• Debugging and logging\n• Testing and mocking\n• Third-party library integration\n\n• **Cautions:**\n• Can make code hard to debug\n• Should be used sparingly\n• Requires @objc compatibility
Question:
Explain the concept of copy-on-write in Swift collections.
Answer:
Copy-on-write (COW) is an optimization where Swift collections share memory until modification occurs.\n\n• **How It Works:**\n• Multiple variables share same memory\n• Copy only happens when one is modified\n• Reduces memory usage and improves performance\n• Automatic in Swift standard collections\n\n\nvar array1 = [1, 2, 3, 4, 5] // Original array\nvar array2 = array1 // Shares memory with array1\n\n// No copy yet - both point to same memory\nprint(array1) // [1, 2, 3, 4, 5]\nprint(array2) // [1, 2, 3, 4, 5]\n\n// Now copy happens\narray2.append(6) // Triggers copy\nprint(array1) // [1, 2, 3, 4, 5]\nprint(array2) // [1, 2, 3, 4, 5, 6]\n\n\n• **Benefits:**\n• Memory efficiency\n• Performance optimization\n• Transparent to developers\n• Maintains value semantics\n\n• **Custom Implementation:**\n\nstruct MyArray {\n var storage: ArrayStorage\n \n func append(_ element: T) {\n if !isKnownUniquelyReferenced(&storage) {\n storage = storage.copy()\n }\n storage.append(element)\n }\n}\n
Question:
What are associated values in Swift enums?
Answer:
Associated values allow Swift enums to store additional data alongside case values.\n\n• **Basic Syntax:**\n\nenum Result {\n case success(T)\n case failure(E)\n}\n\nenum NetworkResponse {\n case success(Data, HTTPURLResponse)\n case failure(Error)\n case loading(progress: Double)\n}\n\n\n• **Pattern Matching:**\n\nlet response = NetworkResponse.success(data, httpResponse)\n\nswitch response {\ncase .success(let data, let response):\n print("Success with \(data.count) bytes")\ncase .failure(let error):\n print("Failed: \(error)")\ncase .loading(let progress):\n print("Loading: \(progress * 100)%")\n}\n\n\n• **Advanced Usage:**\n\nenum Expression {\n case number(Int)\n case addition(Expression, Expression)\n case multiplication(Expression, Expression)\n \n func evaluate() -> Int {\n switch self {\n case .number(let value):\n return value\n case .addition(let left, let right):\n return left.evaluate() + right.evaluate()\n case .multiplication(let left, let right):\n return left.evaluate() * right.evaluate()\n }\n }\n}\n\n\n• **Benefits:**\n• Type-safe data storage\n• Eliminates need for multiple types\n• Powerful pattern matching\n• Recursive data structures
Question:
Explain the difference between lazy and computed properties.
Answer:
Lazy and computed properties serve different purposes in Swift property management.\n\n• **Lazy Properties:**\n• Calculated only when first accessed\n• Stored after first calculation\n• Must be declared with var\n• Cannot have observers\n\n\nclass DataManager {
\n var expensiveResource: ExpensiveClass = {\n print("Creating expensive resource")\n return ExpensiveClass()\n }()\n \n var processedData = self.rawData.map { $0.processed() }\n}\n\n\n• **Computed Properties:**\n• Calculated every time accessed\n• Not stored in memory\n• Can have getter and setter\n• Can have property observers\n\n\nstruct Rectangle {
\n var width: Double\n var height: Double\n \n var area: Double {\n get {\n return width * height\n }\n set {\n // Assuming square for simplicity\n width = sqrt(newValue)\n height = sqrt(newValue)\n }\n }\n}\n\n\n• **When to Use:**\n• **Lazy:** Expensive initialization, optional resources\n• **Computed:** Dynamic values, derived properties\n\n• **Performance:**\n• Lazy: One-time cost, then fast access\n• Computed: Calculation cost on every access
Question:
What is the purpose of the @objc attribute in Swift?
Answer:
The @objc attribute exposes Swift code to the Objective-C runtime, enabling interoperability.\n\n• **Basic Usage:**\n\nclass MyClass: NSObject {\n @ func handleTap() {\n print("Button tapped")\n }\n \n @ var title: String = "Default"\n \n @objc func classMethod() {\n print("Class method called")\n }\n}\n\n\n• **Automatic @objc Inference:**\n• NSObject subclasses\n• Protocol requirements marked @objc\n• Overrides of @objc methods\n• Target-action patterns\n\n\n// Automatic @objc for UIButton target\nbutton.addTarget(self, action: #selector(handleTap), for: .touchUpInside)\n\n\n• **@objc vs @objcMembers:**\n\n@objcMembers\nclass AutoExposedClass: NSObject {\n func method1() {} // Automatically @objc\n func method2() {} // Automatically @objc\n \n @ func swiftOnlyMethod() {} // Opt out\n}\n\n\n• **Limitations:**\n• Performance overhead\n• Limited to Objective-C compatible types\n• Dynamic dispatch\n• Larger binary size\n\n• **Use Cases:**\n• UIKit target-action\n• KVO (Key-Value Observing)\n• Objective-C interop\n• Runtime introspection
Question:
How does Swift handle method dispatch?
Answer:
Swift uses different method dispatch mechanisms for performance and flexibility.\n\n• **Static Dispatch:**\n• Compile-time method resolution\n• Fastest performance\n• Used for structs, final classes, private methods\n\n\nstruct Point {
\n func distance() -> Double { // Static dispatch\n return sqrt(x*x + y*y)\n }\n}\n\nfinal class FinalClass {
\n func method() {} // Static dispatch\n}\n\n\n• **Dynamic Dispatch (V-Table):**\n• Runtime method resolution using virtual table\n• Enables polymorphism\n• Used for class methods by default\n\n\nclass Animal {
\n func makeSound() { // Dynamic dispatch\n print("Some sound")\n }\n}\n\nclass Dog: Animal {\n func makeSound() {\n print("Woof")\n }\n}\n\n\n• **Message Dispatch:**\n• Objective-C runtime dispatch\n• Most flexible but slowest\n• Used with @objc methods\n\n\nclass MyClass: NSObject {\n @objc func dynamicMethod() { // Message dispatch\n print("Dynamic")\n }\n}\n\n\n• **Performance Order:**\n1. Static (fastest)\n2. V-Table dynamic\n3. Message dispatch (slowest)\n\n• **Optimization Tips:**\n• Use final for classes that won't be subclassed\n• Use private for methods not accessed externally\n• Prefer structs when inheritance isn't needed
Question:
What are keypaths in Swift and how are they used?
Answer:
Keypaths provide a way to reference properties as first-class values in Swift.\n\n• **Basic Syntax:**\n\nstruct Person {
\n let name: String\n let age: Int\n}\n\nlet person = Person(name: "Alice", age: 30)\n\n// Keypath creation\nlet nameKeyPath = \Person.name\nlet ageKeyPath = \Person.age\n\n// Accessing values\nlet name = person[keyPath: nameKeyPath] // "Alice"\nlet age = person[keyPath: ageKeyPath] // 30\n\n\n• **Types of Keypaths:**\n\n// ReadOnly keypath\nlet readOnlyPath: KeyPath = \.name\n\n// Writable keypath\nvar mutablePerson = Person(name: "Bob", age: 25)\nlet writablePath: WritableKeyPath = \.age\nmutablePerson[keyPath: writablePath] = 26\n\n// Reference writable (for classes)\nclass MutablePerson {
\n var name: String\n init(name: String) { self.name = name }\n}\nlet refPath: ReferenceWritableKeyPath = \.name\n\n\n• **Practical Applications:**\n\n// Sorting with keypaths\nlet people = [Person(name: "Alice", age: 30), Person(name: "Bob", age: 25)]\nlet sortedByAge = people.sorted(by: \.age)\nlet sortedByName = people.sorted(by: \.name)\n\n// SwiftUI bindings\nstruct ContentView: View {\n @State var person = Person(name: "Alice", age: 30)\n \n var body: some View {\n TextField("Name", text: $person.name)\n }\n}\n\n\n• **Benefits:**\n• Type-safe property references\n• Functional programming patterns\n• SwiftUI data binding\n• Generic algorithms
Question:
Explain the concept of phantom types in Swift.
Answer:
Phantom types are types that exist only at compile time to provide additional type safety.\n\n• **Basic Concept:**\n\nstruct Tagged {\n let value: Value\n \n init(_ value: Value) {\n self.value = value\n }\n}\n\n// Phantom type tags\nenum UserID {}\nenum ProductID {}\n\ntypealias UserIdentifier = Tagged\ntypealias ProductIdentifier = Tagged\n\n\n• **Usage Example:**\n\nfunc getUser(id: UserIdentifier) -> User? {\n // Implementation\n return nil\n}\n\nfunc getProduct(id: ProductIdentifier) -> Product? {\n // Implementation\n return nil\n}\n\nlet userId = UserIdentifier(123)\nlet productId = ProductIdentifier(456)\n\n// Type safe - correct usage\nlet user = getUser(id: userId)\n\n// Compile error - prevents mixing IDs\n// let user = getUser(id: productId) // ❌ Error\n\n\n• **Advanced Example:**\n\nstruct Distance {\n let value: Double\n \n init(_ value: Double) {\n self.value = value\n }\n}\n\nenum Meters {}\nenum Feet {}\n\ntypealias MetersDistance = Distance\ntypealias FeetDistance = Distance\n\n// Type-safe distance calculations\nfunc convert(_ distance: MetersDistance) -> FeetDistance {\n return FeetDistance(distance.value * 3.28084)\n}\n\n\n• **Benefits:**\n• Compile-time type safety\n• Zero runtime cost\n• Prevents logical errors\n• Self-documenting code\n• API design clarity
Question:
Explain Swift's concurrency model with async/await and actors.
Answer:
Swift's modern concurrency model provides structured concurrency with async/await and actors for safe concurrent programming.\n\n• **Async/Await:**\n• Eliminates callback hell and completion handlers\n• Provides sequential-looking asynchronous code\n• Automatic suspension and resumption\n• Structured concurrency with task hierarchies\n\n\nfunc fetchData() async throws -> Data {\n let url = URL(string: "https://api.example.com")!\n let (data, _) = try await URLSession.shared.data(from: url)\n return data\n}\n\n// Usage\nTask {\n do {\n let data = try await fetchData()\n print("Received data: \(data)")\n } catch {\n print("Error: \(error)")\n }\n}\n\n\n• **Actors:**\n• Provide thread-safe access to mutable state\n• Isolate state and ensure serial access\n• Prevent data races at compile time\n• Support async methods and properties\n\n\nactor BankAccount {\n var balance: Double = 0\n \n func deposit(_ amount: Double) {\n balance += amount\n }\n \n func withdraw(_ amount: Double) -> Bool {\n guard balance >= amount else { return false }\n balance -= amount\n return true\n }\n}\n
Question:
What is the difference between struct and class in Swift?
Answer:
Key differences: 1) Value vs Reference types - structs are value types (copied), classes are reference types (shared), 2) Inheritance - classes support inheritance, structs do not, 3) Identity operators - classes use === and !==, structs cannot, 4) Deinitializers - only classes have deinit, 5) Reference counting - only classes use ARC, 6) Mutability - struct methods need mutating keyword to modify properties. Use structs for simple data, classes for complex objects with inheritance.
Question:
Explain Swift's memory layout and ABI stability.
Answer:
Swift's memory layout and ABI stability ensure consistent binary interfaces across compiler versions.\n\n• **Memory Layout:**\n• Value types stored inline\n• Reference types use heap allocation\n• Existential containers for protocols\n• Witness tables for dynamic dispatch\n\n• **ABI Stability:**\n• Binary compatibility across Swift versions\n• Stable since Swift 5.0\n• Enables OS-level Swift runtime\n• Backward compatibility guarantees\n\n• **Layout Optimization:**\n\n// Struct layout is optimized\nstruct OptimizedStruct {
\n let flag: Bool // 1 byte\n let value: Int64 // 8 bytes, aligned\n let small: Int8 // 1 byte, packed\n}\n\n// Class layout includes metadata\nclass MyClass {
\n let isa: UnsafeRawPointer // Class metadata\n let refCount: Int // Reference count\n let property: Int // Actual properties\n}\n\n\n• **Existential Containers:**\n• Store protocol conforming values\n• Inline storage for small values\n• Heap allocation for large values\n• Witness table for method dispatch
Question:
What are opaque return types and how do they work?
Answer:
Opaque return types hide concrete implementation while preserving type identity.\n\n• **Basic Syntax:**\n\nfunc makeCollection() -> some Collection {\n return [1, 2, 3, 4, 5]\n}\n\nfunc makeView() -> some View {\n return Text("Hello, World!")\n}\n\n\n• **Compared to Protocols:**\n\n// Protocol return type (existential)\nfunc makeExistential() -> Collection {\n return [1, 2, 3] // Type erased\n}\n\n// Opaque return type\nfunc makeOpaque() -> some Collection {\n return [1, 2, 3] // Preserves concrete type\n}\n\n\n• **Benefits:**\n• Type identity preservation\n• Better performance (no existential overhead)\n• Enables protocol requirements with Self/associated types\n• Compiler optimizations\n\n• **SwiftUI Usage:**\n\nstruct ContentView: View {\n var body: some View { // Opaque return type\n VStack {\n Text("Title")\n Button("Action") { }\n }\n }\n}\n\n\n• **Limitations:**\n• Single concrete type per function\n• Cannot return different types conditionally\n• Caller cannot know concrete type
Question:
Explain the concept of existential types in Swift.
Answer:
Existential types represent "any type that conforms to a protocol" in Swift.\n\n• **Basic Concept:**\n\nprotocol Drawable {\n func draw()\n}\n\n// Existential type\nvar drawable: Drawable = Circle() // or Rectangle(), etc.\ndrawable.draw() // Dynamic dispatch\n\n\n• **Existential Containers:**\n• Store value and type metadata\n• Witness table for protocol methods\n• Value buffer for inline storage\n\n\n// Internal representation\nstruct ExistentialContainer {
\n var valueBuffer: (Int, Int, Int) // Inline storage\n var type: Any.Type // Type metadata\n var witnessTable: UnsafePointer // Protocol witness table\n}\n\n\n• **Performance Implications:**\n• Dynamic dispatch overhead\n• Potential heap allocation\n• Copy semantics for value types\n\n• **Any vs AnyObject:**\n\n// Any: can hold any type\nvar anything: Any = 42\nanything = "String"\nanything = [1, 2, 3]\n\n// AnyObject: only reference types\nvar anyObject: AnyObject = NSString("Hello")\n// anyObject = 42 // ❌ Error\n\n\n• **Type Erasure Pattern:**\n\nstruct AnySequence: Sequence {\n let _makeIterator: () -> AnyIterator\n \n init(_ sequence: S) where S.Element == Element {\n _makeIterator = { AnyIterator(sequence.makeIterator()) }\n }\n \n func makeIterator() -> AnyIterator {\n return _makeIterator()\n }\n}\n
Question:
How does Swift's type system handle variance?
Answer:
Swift's type system handles variance through careful design of generic constraints and protocols.\n\n• **Variance Types:**\n• **Covariance:** Subtype can be used where supertype expected\n• **Contravariance:** Supertype can be used where subtype expected\n• **Invariance:** Exact type match required\n\n• **Swift's Approach:**\n\n// Swift arrays are invariant\nclass Animal {
}\nclass Dog: Animal {}\n\nvar dogs: [Dog] = [Dog()]\n// var animals: [Animal] = dogs // ❌ Error - not covariant\n\n// But you can convert explicitly\nvar animals: [Animal] = dogs.map { $0 as Animal }\n\n\n• **Function Parameter Variance:**\n\n// Functions are contravariant in parameters\ntypealias DogHandler = (Dog) -> Void\ntypealias AnimalHandler = (Animal) -> Void\n\nfunc processDog(handler: DogHandler) {}\n\nlet animalHandler: AnimalHandler = { animal in }\n// processDog(handler: animalHandler) // ❌ Not allowed\n\n\n• **Protocol Variance:**\n\nprotocol Container {\n associatedtype Item\n func add(_ item: Item)\n}\n\n// Protocols with associated types are invariant\nstruct IntContainer: Container {\n func add(_ item: Int) {}\n}\n\nstruct StringContainer: Container {\n func add(_ item: String) {}\n}\n\n\n• **Workarounds:**\n\n// Use type erasure for variance-like behavior\nprotocol AnyContainer {\n func addAny(_ item: Any)\n}\n\nextension IntContainer: AnyContainer {\n func addAny(_ item: Any) {\n let intItem = item as? Int {\n add(intItem)\n }\n }\n}\n
Question:
What is the difference between static and dynamic member lookup?
Answer:
Swift provides both static and dynamic member lookup for flexible API design.\n\n• **Static Member Lookup:**\n• Resolved at compile time\n• Type-safe and performant\n• Standard Swift behavior\n\n\nstruct Point {
\n let x: Double\n let y: Double\n \n let zero = Point(x: 0, y: 0)\n}\n\nlet origin = Point.zero // Static lookup\n\n\n• **Dynamic Member Lookup:**\n• Resolved at runtime\n• Enables flexible APIs\n• Requires @dynamicMemberLookup\n\n\n@dynamicMemberLookup\nstruct DynamicStruct {
\n var storage: [String: Any] = [:]\n \n subscript(dynamicMember key: String) -> Any? {\n get { return storage[key] }\n set { storage[key] = newValue }\n }\n}\n\nvar dynamic = DynamicStruct()\ndynamic.name = "Swift" // Dynamic lookup\ndynamic.version = 5.5\n\n\n• **Advanced Dynamic Lookup:**\n\n@dynamicMemberLookup\nstruct JSON {
\n let data: [String: Any]\n \n subscript(dynamicMember key: String) -> JSON? {\n let value = data[key] else { return nil }\n let dict = value as? [String: Any] {\n return JSON(data: dict)\n }\n return nil\n }\n}\n\n// Usage\nlet json = JSON(data: ["user": ["name": "Alice", "age": 30]])\nlet userName = json.user?.name // Dynamic chaining\n\n\n• **Use Cases:**\n• JSON/Dictionary wrappers\n• Scripting language bridges\n• Dynamic configuration\n• Builder patterns
Question:
Explain Swift's compilation process and LLVM integration.
Answer:
Swift's compilation process involves multiple stages with LLVM integration for optimization.\n\n• **Compilation Stages:**\n1. **Parsing:** Source code → AST (Abstract Syntax Tree)\n2. **Semantic Analysis:** Type checking, name resolution\n3. **SIL Generation:** Swift Intermediate Language\n4. **SIL Optimization:** High-level optimizations\n5. **LLVM IR Generation:** Lower-level representation\n6. **LLVM Optimization:** Machine-independent optimizations\n7. **Code Generation:** Target-specific machine code\n\n• **Swift Intermediate Language (SIL):**\n\n// Swift source\nfunc add(_ a: Int, _ b: Int) -> Int {\n return a + b\n}\n\n// Simplified SIL representation\nsil @add : $@convention(thin) (Int, Int) -> Int {\nbb0(%0 : $Int, %1 : $Int):\n %2 = builtin "sadd_with_overflow_Int64"(%0 : $Int, %1 : $Int)\n %3 = tuple_extract %2 : $(Int, Builtin.Int1), 0\n return %3 : $Int\n}\n\n\n• **LLVM Integration:**\n• Swift compiler generates LLVM IR\n• LLVM performs optimizations\n• Target-specific code generation\n• Link-time optimization (LTO)\n\n• **Optimization Levels:**\nbash\n# Debug build (no optimization)\nswiftc -Onone source.swift\n\n# Release build (full optimization)\nswiftc -O source.swift\n\n# Size optimization\nswiftc -Osize source.swift\n\n\n• **Whole Module Optimization:**\n• Analyzes entire module together\n• Better inlining decisions\n• Dead code elimination\n• Devirtualization opportunities
Question:
How do you implement custom operators in Swift?
Answer:
Swift allows defining custom operators with specific precedence and associativity.\n\n• **Operator Declaration:**\n\n// Declare operator\ninfix operator **: MultiplicationPrecedence\n\n// Implement operator\nfunc ** (base: Double, exponent: Double) -> Double {\n return pow(base, exponent)\n}\n\n// Usage\nlet result = 2.0 ** 3.0 // 8.0\n\n\n• **Precedence Groups:**\n\nprecedencegroup ExponentiationPrecedence {\n higherThan: MultiplicationPrecedence\n associativity: right\n}\n\ninfix operator **: ExponentiationPrecedence\n\n// Right associative: 2 ** 3 ** 2 = 2 ** (3 ** 2) = 512\n\n\n• **Operator Types:**\n\n// Prefix operator\nprefix operator √\nprefix func √(value: Double) -> Double {\n return sqrt(value)\n}\n\n// Postfix operator\npostfix operator !\npostfix func !(value: Int) -> Int {\n return (1...value).reduce(1, *)\n}\n\n// Usage\nlet root = √16.0 // 4.0\nlet factorial = 5! // 120\n\n\n• **Generic Operators:**\n\ninfix operator <>\n\nfunc <> (lhs: T?, rhs: T?) -> T? {\n return lhs ?? rhs\n}\n\nlet result = nil <> "default" <> "fallback" // "default"\n\n\n• **Best Practices:**\n• Use meaningful symbols\n• Follow existing conventions\n• Document behavior clearly\n• Consider readability impact
Question:
What are result builders and how are they implemented?
Answer:
Result builders enable creating DSL-like syntax by transforming sequences of statements.\n\n• **Basic Result Builder:**\n\n@resultBuilder\nstruct ArrayBuilder {
\n func buildBlock(_ components: T...) -> [T] {\n return Array(components)\n }\n \n func buildOptional(_ component: [T]?) -> [T] {\n return component ?? []\n }\n \n func buildEither(first component: [T]) -> [T] {\n return component\n }\n \n func buildEither(second component: [T]) -> [T] {\n return component\n }\n}\n\n\n• **Usage:**\n\n@ArrayBuilder\nfunc makeArray() -> [String] {\n "First"\n "Second"\n if Bool.random() {\n "Random"\n }\n "Last"\n}\n\nlet array = makeArray() // ["First", "Second", "Random"?, "Last"]\n\n\n• **SwiftUI Example:**\n\n@resultBuilder\nstruct ViewBuilder {
\n func buildBlock(_ content: Content) -> Content where Content: View {\n return content\n }\n \n func buildBlock(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0: View, C1: View {\n return TupleView((c0, c1))\n }\n}\n\nstruct ContentView: View {\n @ViewBuilder\n var body: some View {\n Text("Title")\n Button("Action") { }\n }\n}\n\n\n• **Advanced Features:**\n• buildArray for loops\n• buildLimitedAvailability for availability\n• buildFinalResult for post-processing
Question:
Explain Swift's module system and access control.
Answer:
Swift's module system provides encapsulation and access control at different levels.\n\n• **Module Structure:**\n\n// Module: MyLibrary\n// File: PublicAPI.swift\npublic struct PublicType {
\n let publicProperty: String\n let internalProperty: Int\n let privateProperty: Bool\n \n public init(publicProperty: String) {\n self.publicProperty = publicProperty\n self.internalProperty = 0\n self.privateProperty = false\n }\n}\n\n\n• **Access Levels:**\n• **open:** Subclassable outside module\n• **public:** Accessible outside module\n• **internal:** Accessible within module (default)\n• **fileprivate:** Accessible within file\n• **private:** Accessible within declaration\n\n\nopen class OpenClass {
\n var publicVar = 0\n var internalVar = 0\n var filePrivateVar = 0\n var privateVar = 0\n \n func openMethod() {}\n func publicMethod() {}\n func internalMethod() {}\n func filePrivateMethod() {}\n func privateMethod() {}\n}\n\n\n• **Module Imports:**\n\n// Import entire module\nimport Foundation\n\n// Import specific declarations\nimport struct Foundation.URL\ func Darwin.sqrt\n\n// Import with custom name\nimport MyVeryLongModuleName as Short\n\n\n• **Conditional Compilation:**\n\n#if canImport(UIKit)\nimport UIKit\ntypealias PlatformView = UIView\n#elseif canImport(AppKit)\nimport AppKit\ntypealias PlatformView = NSView\n#endif\n
Question:
How does Swift handle protocol witness tables?
Answer:
Protocol witness tables enable dynamic dispatch for protocol methods in Swift.\n\n• **Witness Table Structure:**\n\nprotocol Drawable {\n func draw()\n func area() -> Double\n}\n\n// Compiler generates witness table\nstruct CircleWitnessTable {
\n let drawFunction: (Circle) -> Void\n let areaFunction: (Circle) -> Double\n}\n\n\n• **Runtime Representation:**\n\n// Existential container\nstruct ProtocolExistential {
\n var valueBuffer: (Int64, Int64, Int64) // 24 bytes inline storage\n var type: Any.Type // Type metadata\n var witnessTable: UnsafePointer // Protocol witness table\n}\n\n\n• **Witness Table Generation:**\n\nstruct Circle: Drawable {\n let radius: Double\n \n func draw() {\n print("Drawing circle")\n }\n \n func area() -> Double {\n return .pi * radius * radius\n }\n}\n\n// Compiler generates:\n// CircleDrawableWitnessTable = {\n// draw: Circle.draw,\n// area: Circle.area\n// }\n\n\n• **Performance Implications:**\n• Indirect function calls\n• Cannot be inlined across module boundaries\n• Runtime type checking overhead\n\n• **Optimization Strategies:**\n\n// Specialization for concrete types\nfunc drawShape(_ shape: T) {\n shape.draw() // Can be statically dispatched\n}\n\n// vs existential\nfunc drawShape(_ shape: Drawable) {\n shape.draw() // Dynamic dispatch through witness table\n}\n
Question:
What is the difference between structural and nominal typing?
Answer:
Swift uses nominal typing with some structural elements, affecting type relationships.\n\n• **Nominal Typing:**\n• Types identified by name/declaration\n• Explicit conformance required\n• Swift's primary approach\n\n\nstruct Point {
\n let x: Double\n let y: Double\n}\n\nstruct Vector {
\n let x: Double\n let y: Double\n}\n\n// Different types despite same structure\nlet point = Point(x: 1, y: 2)\nlet vector = Vector(x: 1, y: 2)\n// point = vector // ❌ Error - different nominal types\n\n\n• **Structural Elements:**\n• Function types are structural\n• Tuple types are structural\n• Closure compatibility\n\n\n// Function types are structural\ntypealias BinaryOperation = (Int, Int) -> Int\ntypealias Calculator = (Int, Int) -> Int\n\nlet add: BinaryOperation = { $0 + $1 }\nlet calc: Calculator = add // ✅ Compatible - same structure\n\n// Tuple compatibility\nlet tuple1: (Int, String) = (1, "hello")\nlet tuple2: (Int, String) = tuple1 // ✅ Same structure\n\n\n• **Protocol Conformance:**\n\nprotocol Equatable {\n static func == (lhs: Self, rhs: Self) -> Bool\n}\n\n// Explicit conformance required (nominal)\nstruct Person: Equatable {\n let name: String\n \n static func == (lhs: Person, rhs: Person) -> Bool {\n return lhs.name == rhs.name\n }\n}\n\n\n• **Benefits of Nominal Typing:**\n• Clear type relationships\n• Explicit intent\n• Better error messages\n• Prevents accidental compatibility
Question:
Explain Swift's approach to memory safety.
Answer:
Swift prioritizes memory safety through various compile-time and runtime mechanisms.\n\n• **Automatic Reference Counting (ARC):**\n• Automatic memory management\n• Compile-time insertion of retain/release\n• Prevents use-after-free\n• Cycle detection warnings\n\n\nclass Node {
\n var value: Int\n var parent: Node? // Prevents cycles\n var children: [Node] = []\n \n init(value: Int) {\n self.value = value\n }\n}\n\n\n• **Initialization Safety:**\n• All properties must be initialized\n• Definite initialization analysis\n• No access before initialization\n\n\nstruct SafeStruct {
\n let value: Int\n let computed: String\n \n init(value: Int) {\n self.value = value\n // Must initialize all properties\n self.computed = "Value: \(value)"\n }\n}\n\n\n• **Optional Safety:**\n• Explicit nil handling\n• Compile-time nil checking\n• Safe unwrapping patterns\n\n\n// Safe optional handling\ let unwrapped = optional {\n // Use unwrapped safely\n}\n\n// Guard for early exit\ let value = optional else {\n return // Must exit scope\n}\n\n\n• **Bounds Checking:**\n\nlet array = [1, 2, 3]\n// let item = array[10] // Runtime error - bounds checking\nlet safeItem = array.indices.contains(10) ? array[10] : nil\n\n\n• **Exclusive Access:**\n• Prevents simultaneous read/write\n• Compile-time and runtime enforcement\n• Memory corruption prevention\n\n\nvar value = 42\nfunc modify(_ x: inout Int) {\n x += 1\n}\n\n// modify(&value) // Safe\n// Cannot have overlapping access\n
Question:
How do you implement custom collection types?
Answer:
Implementing custom collection types requires conforming to specific protocols with careful consideration of performance.\n\n• **Basic Collection Protocol:**\n\nstruct RingBuffer: Collection {\n var buffer: [Element?]\n var head = 0\n var tail = 0\n let capacity: Int\n \n init(capacity: Int) {\n self.capacity = capacity\n self.buffer = Array(repeating: nil, count: capacity)\n }\n \n // Collection requirements\n var startIndex: Int { return head }\n var endIndex: Int { return tail }\n \n func index(after i: Int) -> Int {\n return (i + 1) % capacity\n }\n \n subscript(position: Int) -> Element {\n return buffer[position]!\n }\n}\n\n\n• **Mutable Collection:**\n\nextension RingBuffer: MutableCollection {\n subscript(position: Int) -> Element {\n get { return buffer[position]! }\n set { buffer[position] = newValue }\n }\n}\n\n\n• **Range Replaceable Collection:**\n\nextension RingBuffer: RangeReplaceableCollection {\n init() {\n self.init(capacity: 16)\n }\n \n func replaceSubrange(_ subrange: Range, with newElements: C) where C: Collection, Element == C.Element {\n // Implementation for replacing elements\n }\n}\n\n\n• **Performance Considerations:**\n\n// Lazy collections for performance\nstruct LazyFilterCollection {\n let base: Base\n let predicate: (Base.Element) -> Bool\n \n func makeIterator() -> LazyFilterIterator {\n return LazyFilterIterator(base: base.makeIterator(), predicate: predicate)\n }\n}\n\n\n• **Copy-on-Write Implementation:**\n\nstruct COWArray {\n var storage: ArrayStorage\n \n func append(_ element: Element) {\n if !isKnownUniquelyReferenced(&storage) {\n storage = storage.copy()\n }\n storage.append(element)\n }\n}\n
Question:
What are the performance implications of different Swift features?
Answer:
Different Swift features have varying performance characteristics that affect application performance.\n\n• **Value vs Reference Types:**\n\n// Value types (faster for small data)\nstruct Point {
let x, y: Double }\nlet points = Array(repeating: Point(x: 1, y: 2), count: 1000)\n\n// Reference types (better for large data)\nclass LargeData {
\n let data = Array(repeating: 0, count: 10000)\n}\nlet objects = Array(repeating: LargeData(), count: 1000)\n\n\n• **Method Dispatch Performance:**\n\n// Static dispatch (fastest)\nstruct FastStruct {
\n func method() {} // Static dispatch\n}\n\n// V-table dispatch (medium)\nclass RegularClass {
\n func method() {} // V-table dispatch\n}\n\n// Message dispatch (slowest)\nclass ObjCClass: NSObject {\n @objc func method() {} // Message dispatch\n}\n\n\n• **Collection Performance:**\n\n// Array: O(1) access, O(n) insertion\nvar array = [1, 2, 3]\narray.append(4) // O(1) amortized\narray.insert(0, at: 0) // O(n)\n\n// Set: O(1) average lookup\nvar set: Set = [1, 2, 3]\nset.contains(2) // O(1) average\n\n// Dictionary: O(1) average access\nvar dict = ["key": "value"]\ndict["key"] // O(1) average\n\n\n• **String Performance:**\n\n// Inefficient string concatenation\nvar result = ""\nfor i in 0..<1000 {\n result += "\(i)" // O(n²) complexity\n}\n\n// Efficient string building\nvar parts: [String] = []\nfor i in 0..<1000 {\n parts.append("\(i)")\n}\nlet result = parts.joined() // O(n) complexity\n\n\n• **Memory Allocation:**\n\n// Stack allocation (fast)\nlet value = 42\nlet point = Point(x: 1, y: 2)\n\n// Heap allocation (slower)\nlet object = MyClass()\nlet array = [1, 2, 3, 4, 5]\n\n\n• **Optimization Tips:**\n• Use value types for small data\n• Prefer final classes when inheritance not needed\n• Use lazy properties for expensive computations\n• Avoid unnecessary ARC traffic\n• Profile before optimizing
Question:
Explain Swift's interoperability with C and Objective-C.
Answer:
Swift provides seamless interoperability with C and Objective-C through various mechanisms.\n\n• **C Interoperability:**\n\n// Import C functions\nimport Darwin\n\n// Use C functions directly\nlet result = sqrt(16.0) // C math function\nlet ptr = malloc(1024) // C memory allocation\ndefer { free(ptr) } // Cleanup\n\n// C structs\nvar point = CGPoint(x: 10, y: 20)\nvar rect = CGRect(origin: point, size: CGSize(width: 100, height: 50))\n\n\n• **Objective-C Interoperability:**\n\n// Import Objective-C\nimport Foundation\n\n// Use Objective-C classes\nlet string = NSString(string: "Hello")\nlet array = NSMutableArray()\narray.add("Item")\n\n// Bridging\nlet swiftString: String = string as String\nlet swiftArray: [Any] = array as Array\n\n\n• **Bridging Headers:**\nobjc\n// BridgingHeader.h\n#import "MyObjCClass.h"\n\n@interface MyObjCClass : NSObject\n- (void)doSomething;\n@property (nonatomic, strong) NSString *name;\n@end\n\n\n\n// Swift usage\nlet objcInstance = MyObjCClass()\nobjcInstance.name = "Swift"\nobjcInstance.doSomething()\n\n\n• **Type Bridging:**\n\n// Automatic bridging\nlet nsString: NSString = "Swift String" // String → NSString\nlet swiftString: String = nsString as String // NSString → String\n\n// Collection bridging\nlet nsArray: NSArray = [1, 2, 3] // Array → NSArray\nlet swiftArray: [Int] = nsArray as! [Int] // NSArray → Array\n\n\n• **Memory Management:**\n\n// ARC works with Objective-C\nclass SwiftClass {
\n @ func callableFromObjC() {}\n}\n\n// Toll-free bridging\nlet cfString: CFString = "Hello" as CFString\nlet nsString: NSString = cfString // Toll-free bridged\n\n\n• **Performance Considerations:**\n• Bridging has overhead\n• Prefer native Swift types\n• Use @objc judiciously\n• Consider Core Foundation for performance-critical code
Question:
How does Swift's ownership system work?
Answer:
Swift's ownership system manages memory automatically while preventing common memory errors.\n\n• **Reference Counting:**\n\nclass Resource {
\n let name: String\n init(name: String) {\n self.name = name\n print("\(name) created")\n }\n deinit {\n print("\(name) destroyed")\n }\n}\n\nvar resource1: Resource? = Resource(name: "Resource1") // RC = 1\nvar resource2 = resource1 // RC = 2\nresource1 = nil // RC = 1\nresource2 = nil // RC = 0, deinit called\n\n\n• **Weak References:**\n\nclass Parent {
\n var children: [Child] = []\n deinit { print("Parent deallocated") }\n}\n\nclass Child {
\n var parent: Parent? // Prevents retain cycle\n init(parent: Parent) {\n self.parent = parent\n parent.children.append(self)\n }\n deinit { print("Child deallocated") }\n}\n\n\n• **Unowned References:**\n\nclass Customer {
\n let name: String\n var card: CreditCard?\n init(name: String) { self.name = name }\n deinit { print("\(name) is being deinitialized") }\n}\n\nclass CreditCard {
\n let number: UInt64\n let customer: Customer // Always has a customer\n init(number: UInt64, customer: Customer) {\n self.number = number\n self.customer = customer\n }\n deinit { print("Card #\(number) is being deinitialized") }\n}\n\n\n• **Closure Capture Lists:**\n\nclass HTMLElement {
\n let name: String\n let text: String?\n \n var asHTML: () -> String = { [unowned self] in\n let text = self.text {\n return "<\(self.name)>\(text)\(self.name)>"\n } else {\n return "<\(self.name) />"\n }\n }\n \n init(name: String, text: String? = nil) {\n self.name = name\n self.text = text\n }\n \n deinit {\n print("\(name) is being deinitialized")\n }\n}\n\n\n• **Value Type Ownership:**\n\n// Value types have automatic ownership\nstruct Data {
\n var content: [Int]\n}\n\nvar data1 = Data(content: [1, 2, 3])\nvar data2 = data1 // Copy created\ndata2.content.append(4) // Only affects data2\n
Question:
What are the advanced features of Swift's pattern matching?
Answer:
Swift's pattern matching provides powerful and expressive ways to destructure and match data.\n\n• **Advanced Enum Matching:**\n\nenum Result {\n case success(Success)\n case failure(Failure)\n}\n\nenum NetworkError {\n case timeout\n case serverError(Int)\n case noConnection\n}\n\nlet result: Result = .failure(.serverError(500))\n\nswitch result {\ncase .success(let data) where data.count > 100:\n print("Large success: \(data)")\ncase .success(let data):\n print("Success: \(data)")\ncase .failure(.serverError(let code)) where code >= 500:\n print("Server error: \(code)")\ncase .failure(.serverError(let code)):\n print("Client error: \(code)")\ncase .failure(.timeout):\n print("Request timed out")\ncase .failure(.noConnection):\n print("No network connection")\n}\n\n\n• **Tuple and Value Binding:**\n\nlet coordinates = [(0, 0), (1, 0), (1, 1), (0, 1)]\n\nfor coordinate in coordinates {\n switch coordinate {\n case (0, 0):\n print("Origin")\n case (let x, 0):\n print("On x-axis at \(x)")\n case (0, let y):\n print("On y-axis at \(y)")\n case (let x, let y) where x == y:\n print("Diagonal at (\(x), \(y))")\n case (let x, let y):\n print("Point at (\(x), \(y))")\n }\n}\n\n\n• **Optional Pattern Matching:**\n\nlet optionals: [String?] = ["Hello", nil, "World", nil]\n\nfor case let .some(value) in optionals {\n print("Found: \(value)") // Only prints non-nil values\n}\n\n// Pattern matching in if-case\nlet someValue: Any = 42\nif let number as Int = someValue {\n print("Integer: \(number)")\n}\n\n\n• **Custom Pattern Matching:**\n\nstruct Range {
\n let lower: Int\n let upper: Int\n \n static func ~= (pattern: Range, value: Int) -> Bool {\n return pattern.lower <= value && value <= pattern.upper\n }\n}\n\nlet range = Range(lower: 10, upper: 20)\nlet value = 15\n\nswitch value {\ncase range:\n print("Value is in range")\ndefault:\n print("Value is out of range")\n}\n\n\n• **Expression Patterns:**\n\nlet numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\n// Filter using pattern matching\nlet evenNumbers = numbers.filter {\n if let x where x % 2 == 0 = $0 {\n return true\n }\n return false\n}\n\n// More concise\nlet evens = numbers.compactMap { $0 % 2 == 0 ? $0 : nil }\n