IOS Interview Questions and Answers


What is Swift? What are its key features?
  • Swift is a powerful and intuitive programming language for macOS, iOS, watchOS, tvOS, and Linux. Key features include:
    • Safety: Designed to eliminate common programming errors, especially around optionals and memory management.
    • Speed: High performance due to aggressive optimization.
    • Modern Syntax: Expressive and readable syntax, inspired by modern programming language concepts.
    • Interoperability: Seamlessly works with Objective-C code.
    • Playgrounds: Interactive environment for experimenting with Swift code.
    • Open Source: The Swift language is open source.
Explain Optionals in Swift. Why are they important?
  • Optionals are a feature in Swift that handle the absence of a value. An Optional variable can either contain a value or be `nil` (meaning it contains no value). They are important because they enforce nil-safety at compile time, preventing runtime errors that are common in languages like Objective-C where a variable could unexpectedly be `nil`.
What is Optional Binding? How is it used?
  • Optional Binding is a way to safely unwrap an Optional and assign its value to a temporary constant or variable if the Optional contains a value. It's typically used with `if let` or `guard let`.
    
    if let unwrappedValue = optionalValue {
        // Use unwrappedValue here
    } else {
        // optionalValue is nil
    }
    
    guard let unwrappedValue = optionalValue else {
        // Handle nil case
        return
    }
    // Use unwrappedValue here
            
What is Optional Chaining? How is it used?
  • Optional Chaining is a way to safely access properties, methods, or subscripts on an Optional value that might be `nil`. If any part of the chain is `nil`, the entire expression fails gracefully and returns `nil`. It's used with the `?` symbol after the optional value.
    
    let roomCount = john.residence?.numberOfRooms
            
Explain the difference between `let` and `var` in Swift.
  • `let` is used to declare constants. Once a value is assigned to a `let` constant, it cannot be changed.
  • `var` is used to declare variables. The value of a `var` variable can be changed after it is initialized.
What are Structs and Classes in Swift? What are the key differences?
  • Both Structs and Classes are used to define custom data types with properties and methods.
    • Structs: Value types. Copies are created when assigned or passed to functions. Stored on the stack (generally). No inheritance.
    • Classes: Reference types. References to the same instance are created when assigned or passed. Stored on the heap. Support inheritance.
  • Key Differences: Inheritance (Classes only), Type Casting (Classes only), Deinitializers (Classes only), Reference Counting (Classes only), Mutability (Structs require `mutating` keyword for modifying properties in a method).
What is Automatic Reference Counting (ARC)? How does it work?
  • ARC is Swift's memory management system. It automatically tracks and manages the memory usage of your app's instances. When an instance is no longer needed (has no strong references pointing to it), ARC deallocates the memory used by that instance. It helps prevent memory leaks and dangling pointers.
Explain Strong Reference Cycles. How can they be resolved?
  • A Strong Reference Cycle occurs when two or more instances hold strong references to each other, preventing ARC from deallocating them even when they are no longer needed by other parts of the program. They can be resolved using:
    • Weak References: Used when one instance's lifetime can be shorter than the other. The weak reference does not keep a strong hold on the instance it refers to, allowing ARC to deallocate it. Declared with the `weak` keyword.
    • Unowned References: Used when one instance's lifetime is guaranteed to be *at least* as long as the other. The unowned reference also does not keep a strong hold but assumes the instance will always be there. Declared with the `unowned` keyword.
What is a Protocol in Swift? How is it used?
  • A Protocol defines a blueprint of methods, properties, and other requirements that a class, struct, or enum must conform to. It's used to define a contract or capability that types can adopt. Protocols enable polymorphism and are fundamental to Swift's design patterns (like delegation).
What is Delegation? Provide an example.
  • Delegation is a design pattern where an object (the delegate) acts on behalf of another object (the delegating object) to respond to events or provide data. It's implemented using protocols.
    
    protocol MyDelegate: AnyObject { // Use AnyObject for weak references
        func didSomethingImportant(with data: String)
    }
    
    class MyObject {
        weak var delegate: MyDelegate?
    
        func performAction() {
            // ... do something ...
            delegate?.didSomethingImportant(with: "Some data")
        }
    }
    
    class MyViewController: UIViewController, MyDelegate {
        let myObject = MyObject()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            myObject.delegate = self
        }
    
        func didSomethingImportant(with data: String) {
            print("Delegate received data: \(data)")
        }
    }
            
What is a Closure in Swift?
  • Closures are self-contained blocks of functionality that can be passed around and used in your code. They can capture and store references to any constants and variables from the context in which they are defined. They are similar to blocks in Objective-C or lambdas in other languages.
Explain the difference between `@escaping` and non-`@escaping` closures.
  • Non-`@escaping` (default): The closure is executed within the scope of the function it's passed to. It cannot outlive the function call.
  • `@escaping`: The closure can be stored and executed *after* the function it's passed to returns. This is common for asynchronous operations (like network requests) or when storing closures in properties. Escaping closures require careful consideration of strong reference cycles.
What is Grand Central Dispatch (GCD)? How is it used for concurrency?
  • GCD is a low-level C-based API provided by Apple for managing concurrent operations. It works with dispatch queues. You submit tasks (closures or functions) to dispatch queues, and GCD manages the execution of those tasks on a pool of threads. It simplifies concurrent programming compared to managing threads directly.
Explain the difference between Serial and Concurrent Dispatch Queues.
  • Serial Queue: Executes tasks one at a time, in the order they were added. Guarantees that tasks will not run simultaneously on that queue.
  • Concurrent Queue: Executes tasks concurrently, meaning multiple tasks can run at the same time. The order of execution is not guaranteed, and the number of tasks running simultaneously depends on system resources.
What is the Main Thread (or UI Thread)? Why is it important?
  • The Main Thread is the primary thread where all UI updates must occur. It handles user interactions, drawing the UI, and processing events. Performing long-running or blocking operations on the Main Thread will freeze your UI, leading to a poor user experience. All UI modifications must be dispatched to the Main Thread.
How do you perform a task on a background thread using GCD? How do you update the UI after the task is complete?
  • To perform a task on a background thread, you dispatch it to a background concurrent queue:
    
    DispatchQueue.global(qos: .background).async {
        // Perform long-running task here
    
        // Once done, update the UI on the main thread
        DispatchQueue.main.async {
            // Update UI elements here
        }
    }
            
What is UIKit? What are its core responsibilities?
  • UIKit is Apple's traditional framework for building user interfaces for iOS, iPadOS, and tvOS. Its core responsibilities include:
    • Managing the user interface (views, controls).
    • Handling user interactions (touches, gestures).
    • Managing application lifecycle and events.
    • Handling layout and presentation.
    • Integrating with system services (networking, data, etc.).
What is SwiftUI? How is it different from UIKit?
  • SwiftUI is Apple's modern, declarative framework for building user interfaces across all Apple platforms. It's different from UIKit in that it uses a declarative syntax: you describe what your UI should look like based on the current state, and the framework handles updating the UI when the state changes. UIKit is imperative: you explicitly tell the system how to build and update the UI step-by-step.
Explain the MVC (Model-View-Controller) architectural pattern. How does it apply to iOS development?
  • MVC is a common architectural pattern used in iOS development (especially with UIKit).
    • Model: Represents the data and business logic of the application. It is independent of the UI.
    • View: Represents the user interface. It displays data from the Model and sends user input to the Controller. It should not contain business logic.
    • Controller: Acts as an intermediary between the Model and the View. It receives user input from the View, updates the Model, and updates the View based on changes in the Model.
  • In iOS, `UIViewController` is the primary Controller class. `UIView` and its subclasses are the View. Your custom data structures and business logic form the Model.
What are the drawbacks of MVC in iOS? (Massive View Controller)
  • In iOS MVC, View Controllers often become bloated and responsible for too many tasks (handling UI logic, data fetching, business logic, navigation). This leads to the "Massive View Controller" problem, making code hard to maintain, test, and reuse.
What is the difference between a ViewController and a View?
  • A View (`UIView`) is a rectangular area on the screen responsible for drawing content and handling touches within its bounds. It's a UI element.
  • A ViewController (`UIViewController`) manages a hierarchy of Views. It's responsible for the lifecycle of its views, handling user interactions, and coordinating between the Model and the View. It's the controller in MVC.
Explain the ViewController lifecycle methods (e.g., `viewDidLoad`, `viewWillAppear`).
  • `viewDidLoad()`: Called after the controller's view is loaded into memory. This is where you perform initial setup that only needs to happen once (e.g., setting up constraints, loading data).
  • `viewWillAppear(_:)` : Called just before the view appears on the screen. Use this for tasks that need to happen every time the view is about to become visible (e.g., refreshing data).
  • `viewDidAppear(_:)`: Called after the view has been presented on the screen. Use this for tasks that require the view to be fully visible (e.g., starting animations).
  • `viewWillDisappear(_:)`: Called just before the view disappears from the screen. Use this for cleanup or saving state.
  • `viewDidDisappear(_:)`: Called after the view has been removed from the screen. Use this for final cleanup or stopping ongoing tasks.
  • `viewDidLayoutSubviews()`: Called after the view controller's view has laid out its subviews. Useful for making adjustments after layout changes.
  • `updateViewConstraints()`: Called when the view controller's view needs to update its constraints.
What is Auto Layout? How does it work?
  • Auto Layout is a constraint-based layout system that allows you to create adaptive user interfaces that automatically adjust to different screen sizes, orientations, and device types. You define relationships (constraints) between UI elements, and Auto Layout calculates the position and size of each element based on these constraints.
How do you implement Auto Layout in Interface Builder and programmatically?
  • Interface Builder: Use the Auto Layout features in Xcode's Storyboard or XIB editor to add, modify, and resolve constraints visually.
  • Programmatically: Use the `NSLayoutConstraint` class or the Anchor APIs (`.topAnchor`, `.leadingAnchor`, etc.) to create and activate constraints in code. The Anchor APIs are generally preferred for their readability.
What is a Table View (UITableView)? What protocols are used with it?
  • A Table View is a UI element used to display data in a scrollable list of rows. It's commonly used for displaying lists of items. The primary protocols used are:
    • `UITableViewDataSource`: Provides the data to the table view (number of sections, number of rows, cell content).
    • `UITableViewDelegate`: Handles table view appearance and behavior (row selection, row height, section headers/footers).
What is a Collection View (UICollectionView)? How is it different from a Table View?
  • A Collection View is a UI element used to display data in customizable layouts (grids, lists, custom layouts). It's more flexible than a Table View. While a Table View is limited to a single column list, a Collection View can arrange items in multiple columns, rows, or complex patterns. It uses `UICollectionViewDataSource` and `UICollectionViewDelegate` (similar to Table View) and `UICollectionViewLayout` to define the arrangement of items.
Explain the concept of Cell Reuse in Table Views and Collection Views. Why is it important?
  • Cell Reuse is a performance optimization technique. Instead of creating a new cell for each row/item, Table Views and Collection Views maintain a pool of reusable cells. When a cell scrolls off-screen, it's added to the reuse pool. When a new cell needs to be displayed, the system tries to dequeue a reusable cell from the pool instead of creating a new one. This is important for performance, especially with long lists, as it reduces memory usage and rendering overhead.
What is Core Data? What are its main components?
  • Core Data is Apple's framework for managing the model layer of your application. It provides an object-oriented way to interact with persistent data. It's not a database itself, but an object graph management framework that can use various persistent stores (SQLite, XML, binary, in-memory). Main components include:
    • Managed Object Model: Defines the schema (entities, attributes, relationships).
    • Persistent Store Coordinator: Manages the persistent stores and acts as a bridge between the managed object context and the stores.
    • Managed Object Context: The scratchpad where you interact with managed objects (create, fetch, update, delete).
    • Managed Objects: Instances of your data entities.
How do you perform data fetching using Core Data? (NSFetchRequest)
  • You use `NSFetchRequest` to define criteria for fetching managed objects from the persistent store. You specify the entity to fetch, optional predicates (filtering), sort descriptors, and other fetch options. You then execute the fetch request on a `NSManagedObjectContext`.
What is the Keychain? When should you use it?
  • The Keychain is a secure storage system provided by iOS for storing small pieces of sensitive information, such as passwords, certificates, and other secrets. You should use it for any data that needs to be stored securely and persist across app installations (within the same device and user account).
What is User Defaults? When should you use it?
  • User Defaults is a simple key-value storage system for storing small amounts of non-sensitive data, typically user preferences or settings. It's easy to use but not suitable for large amounts of data or sensitive information. Data is stored in a Property List file.
What is URLSession? How do you make a network request?
  • URLSession is Apple's framework for handling network requests. You create a `URLSession` instance (often using the shared singleton), then create a `URLSessionDataTask` (or download/upload task) with the URL and a completion handler. You then call `resume()` on the task to start the request.
Explain the `Codable` protocol in Swift. How does it simplify JSON parsing?
  • `Codable` is a type alias for the `Encodable` and `Decodable` protocols. By making your custom types conform to `Codable`, Swift can automatically generate the code needed to convert instances of your type to and from external representations like JSON or Property Lists. This significantly simplifies JSON parsing compared to manual parsing.
What is App Transport Security (ATS)?
  • ATS is a security feature introduced in iOS 9 that enforces secure connections between your app and web services. By default, it requires connections to use HTTPS with specific security configurations. You can configure exceptions, but it's recommended to use secure connections whenever possible.
What are Push Notifications? How do they work?
  • Push Notifications are messages sent from a server to a user's device, even when the app is not running. They involve:
    • Your app registering with APNs (Apple Push Notification service).
    • Your server sending a notification payload to APNs.
    • APNs delivering the notification to the user's device.
    • The device displaying the notification or waking up the app.
What is the difference between Local and Push Notifications?
  • Local Notifications: Scheduled by the app itself and delivered by the operating system on the same device. Do not require a server connection.
  • Push Notifications: Sent from a remote server via APNs to the user's device. Require server-side implementation and APNs integration.
Explain the concept of Background Modes. Name a few examples.
  • Background Modes allow your app to perform certain tasks while it's in the background, even when the user is not actively using it. Examples include:
    • Audio playback.
    • Location updates.
    • VoIP calls.
    • Background fetch (periodically fetching new content).
    • Background processing (performing CPU-intensive tasks).
What is Grand Central Dispatch (GCD)? How does it handle threads? (Revisited)
  • GCD manages a pool of threads and executes tasks submitted to dispatch queues on those threads. You don't directly manage threads with GCD; you define tasks and queues, and GCD handles the thread management efficiently.
What is an Operation Queue? How is it different from a Dispatch Queue?
  • Operation Queues are a higher-level abstraction built on top of GCD. They manage `Operation` objects (units of work). Operation Queues support dependencies between operations, cancellation, and pausing/resuming queues. Dispatch Queues are a more low-level API for submitting blocks of code.
Explain the concept of Dependencies between Operations in an Operation Queue.
  • You can define dependencies between `Operation` objects in an `OperationQueue`. An operation will not start until all of its dependencies have finished executing. This is useful for ensuring tasks are performed in a specific order.
What is Core Location? How do you get the user's location?
  • Core Location is the framework for determining the user's geographic location and orientation. To get the user's location, you create a `CLLocationManager` instance, set its delegate, request authorization from the user, and call `startUpdatingLocation()`. The location updates are delivered to the delegate methods.
What is MapKit? How do you display a map?
  • MapKit is the framework for embedding maps in your app. You add an `MKMapView` to your UI and set its delegate. You can configure the map type, region, add annotations, overlays, etc.
What are Annotations in MapKit? How do you add them?
  • Annotations are visual markers on a map representing points of interest. You create objects that conform to the `MKAnnotation` protocol (typically by providing a coordinate and title/subtitle) and add them to the `MKMapView` using the `addAnnotation(_:)` method.
What is XCTest? How do you write unit tests?
  • XCTest is Apple's framework for writing unit tests, UI tests, and performance tests. To write a unit test, you create a test class that subclasses `XCTestCase`. Inside this class, you write test methods (starting with `test`). You use assertion methods (e.g., `XCTAssertEqual`, `XCTAssertTrue`) to verify the expected behavior of your code.
What is UI Testing? How is it different from Unit Testing?
  • UI Testing (using XCUITesting) tests the user interface of your application from the user's perspective. It interacts with UI elements (tapping buttons, entering text) and verifies the UI state. Unit Testing tests individual units of code (functions, classes) in isolation, without involving the UI.
What is Internationalization (I18n) and Localization (L10n)? How do you implement them in iOS?
  • Internationalization (I18n): Designing your app so it can be adapted to various languages and regions without engineering changes. This involves separating localizable content (strings, images, dates) from the code.
  • Localization (L10n): The process of adapting your internationalized app to a specific language and region by translating text and providing localized resources.
  • In iOS, you use `.strings` files for localizing text, manage localized assets in Asset Catalogs, and use `NSLocalizedString` for accessing localized strings.
What is Accessibility in iOS development? How do you make your app accessible?
  • Accessibility is about making your app usable by people with disabilities (visual, auditory, motor, cognitive). You make your app accessible by:
    • Setting accessibility labels and hints for UI elements.
    • Using appropriate accessibility traits.
    • Supporting Dynamic Type for adjustable font sizes.
    • Ensuring sufficient color contrast.
    • Providing alternative text for images.
    • Testing with VoiceOver and other accessibility features.
Explain the App Life Cycle in iOS.
  • The App Life Cycle refers to the different states an app can be in:
    • Not Running: The app is not launched or has been terminated.
    • Inactive: The app is in the foreground but not receiving events (e.g., during a phone call).
    • Active: The app is in the foreground and receiving events.
    • Background: The app is in the background and executing code (e.g., for background tasks).
    • Suspended: The app is in the background but not executing code. The system can terminate it to free up resources.
  • Key delegate methods in `AppDelegate` (or `SceneDelegate` for newer apps) handle state transitions (e.g., `applicationDidBecomeActive`, `applicationDidEnterBackground`).
What is a Delegate in iOS development? (Revisited)
  • A Delegate is an object that acts on behalf of another object. It's a design pattern used extensively in iOS frameworks (like `UITableViewDelegate`, `CLLocationManagerDelegate`) to allow customization of behavior without subclassing.
What is a Singleton? When is it appropriate to use?
  • A Singleton is a design pattern that ensures only one instance of a class exists throughout the application's lifetime and provides a global point of access to that instance. It's appropriate for resources that are shared globally and should only have one instance (e.g., a network manager, a user session manager). However, overuse can lead to tightly coupled code and make testing difficult.
What is NotificationCenter? How is it used?
  • NotificationCenter is a mechanism for broadcasting messages (notifications) throughout your application. Objects can register as observers for specific notifications, and other objects can post those notifications. It's a loose coupling mechanism, where the sender doesn't need to know about the receivers.
What is Key-Value Observing (KVO)?
  • KVO is a mechanism that allows an object to observe changes to a property of another object. When the property's value changes, the observer is notified. It's typically used for observing changes in the Model layer from the Controller or View layer. It's more common in Objective-C and UIKit; SwiftUI and Combine offer more modern alternatives.
What is Property Observers (`didSet`, `willSet`) in Swift?
  • Property Observers allow you to execute code before (`willSet`) and after (`didSet`) a property's value changes. They are useful for reacting to property changes within the same object.
What is the difference between a strong reference and a weak reference? (Revisited)
  • Strong Reference: Increases the reference count of the object it points to. Prevents the object from being deallocated as long as a strong reference exists.
  • Weak Reference: Does not increase the reference count. Allows the object to be deallocated if no strong references exist. The weak reference automatically becomes `nil` when the object is deallocated. Used to break strong reference cycles where one object's lifetime can be shorter.
What is an Unowned Reference? How is it different from a Weak Reference? (Revisited)
  • An Unowned Reference also does not increase the reference count. It assumes that the object it points to will always exist as long as the unowned reference exists. If the object is deallocated while an unowned reference still points to it, accessing the unowned reference will cause a runtime crash. Used to break strong reference cycles where one object's lifetime is guaranteed to be *at least* as long as the other.
What is the difference between a class method and an instance method in Swift?
  • Instance Method: Belongs to an instance of a class. Called on a specific object (`myObject.myMethod()`). Can access and modify instance properties.
  • Class Method: Belongs to the class itself (or type). Called on the class type (`MyClass.myTypeMethod()`). Marked with the `class` or `static` keyword. Can only access type properties and methods.
What is a Computed Property in Swift?
  • A Computed Property calculates its value rather than storing it directly. It's defined with a `get` clause (required) and an optional `set` clause. They don't have storage space; their value is computed every time they are accessed.
What is a Stored Property in Swift?
  • A Stored Property stores a value as part of an instance of a class or struct. They have storage space allocated for them.
What is a Property Wrapper? Provide an example. (Swift 5.1+)
  • A Property Wrapper is a type that adds a layer of separation between code that manages how a property is stored and code that defines a property. They allow you to define reusable logic for property access and modification. Examples include `@State` and `@Binding` in SwiftUI.
    
    @propertyWrapper
    struct Clamped {
        private var value: Int
        private let range: ClosedRange
    
        init(wrappedValue: Int, _ range: ClosedRange) {
            self.range = range
            self.value = max(range.lowerBound, min(range.upperBound, wrappedValue))
        }
    
        var wrappedValue: Int {
            get { value }
            set { value = max(range.lowerBound, min(range.upperBound, newValue)) }
        }
    }
    
    struct MyStruct {
        @Clamped(0...100) var progress: Int = 0
    }
            
What is the difference between `Any` and `AnyObject` in Swift?
  • `Any`: Can represent an instance of any type, including function types.
  • `AnyObject`: Can represent an instance of any *class* type.
  • Use `Any` when you need to store values of any type, including structs, enums, and functions. Use `AnyObject` when you specifically need to work with class instances.
What is Type Casting? How is it done in Swift?
  • Type Casting is a way to check the type of an instance or treat an instance as a different superclass or subclass. It's done using the `is` and `as` operators:
    • `is`: Checks if an instance is of a certain type (returns Bool).
    • `as?`: Tries to downcast to a specific type, returning an optional of that type (returns `nil` if the cast fails).
    • `as!`: Forces a downcast to a specific type. Will cause a runtime crash if the cast fails. Use with caution.
    • `as`: Used for upcasting (always succeeds) or bridging between Swift and Objective-C types.
What is Error Handling in Swift? How do you use `try`, `catch`, `throw`, `throws`?
  • Swift's error handling allows you to write code that can fail and propagate the reason for failure.
    • `throws`: Indicates that a function, method, or closure can throw an error.
    • `throw`: Used inside a throwing function to throw an error.
    • `try`: Used when calling a throwing function.
      • `try?`: Calls a throwing function and returns an optional result (`nil` if an error is thrown).
      • `try!`: Calls a throwing function and forces unwrapping the result. Crashes if an error is thrown. Use with caution.
      • `try`: Used within a `do-catch` block.
    • `do-catch`: Used to handle errors thrown by throwing functions.
What is Generics in Swift? Provide an example.
  • Generics allow you to write flexible, reusable functions and types that can work with any type, while still providing type safety. They are placeholder types that are determined at compile time.
    
    func swapTwoValues(_ a: inout T, _ b: inout T) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
            
What is Protocol-Oriented Programming? How does it relate to Swift?
  • Protocol-Oriented Programming (POP) is a programming paradigm that emphasizes the use of protocols to define behavior and composition. Swift is designed to be protocol-oriented. Instead of relying heavily on class inheritance, you define capabilities using protocols and provide default implementations using protocol extensions. This promotes code reuse, flexibility, and testability.
What is a Protocol Extension? Provide an example.
  • A Protocol Extension allows you to provide default implementations for methods and computed properties defined in a protocol. Types conforming to the protocol can use these default implementations or provide their own.
    
    protocol Greetable {
        var name: String { get }
        func greet() -> String
    }
    
    extension Greetable {
        func greet() -> String {
            return "Hello, \(name)!"
        }
    }
    
    struct Person: Greetable {
        let name: String
        // Uses the default greet() implementation
    }
            
What is the difference between `self` and `Self` in Swift?
  • `self` (lowercase): Refers to the *instance* of the type (class, struct, enum) within its own methods.
  • `Self` (uppercase): Refers to the *type* itself (class, struct, enum) within its own methods or type methods. It's often used in protocols to refer to the conforming type.
What is Initialization in Swift? Explain `init` and `deinit`.
  • Initialization is the process of preparing an instance of a class, struct, or enum for use. It involves setting initial values for stored properties and performing any other setup required. Initializers are defined using the `init` keyword.
  • Deinitialization is the process of deallocating an instance of a class when it's no longer needed. Deinitializers are defined using the `deinit` keyword (classes only). They are used for cleanup before the instance is removed from memory.
What is the difference between a Failable Initializer and a Non-Failable Initializer?
  • Failable Initializer (`init?` or `init!`): Can return `nil` if the initialization fails (e.g., invalid input).
  • Non-Failable Initializer (`init`): Guaranteed to create a valid instance.
Explain the concept of Designated Initializers and Convenience Initializers in Classes.
  • Designated Initializers: Primary initializers for a class. They must fully initialize all properties introduced by their class and call a designated initializer from their immediate superclass.
  • Convenience Initializers (`convenience init`): Secondary initializers that must call another initializer from the *same* class. They are used to provide alternative ways to create an instance. They must eventually call a designated initializer.
What is the purpose of the `required` keyword for initializers?
  • The `required` keyword ensures that every subclass of a class must implement that initializer. It's often used with initializers defined in protocols to ensure that conforming classes provide a specific initializer.
What is the difference between a Synchronous and an Asynchronous operation?
  • Synchronous: An operation that blocks the current thread until it completes. The program waits for the operation to finish before moving to the next line of code.
  • Asynchronous: An operation that does not block the current thread. It starts the operation and allows the program to continue executing other code. The operation completes at a later time, typically notifying the caller via a completion handler or callback.
What are Escaping Closures used for? (Revisited)
  • Escaping closures are used for asynchronous operations (network requests, timers), callbacks, and storing closures in properties where the closure's lifetime might exceed the function call's lifetime.
What is Combine? How is it used for reactive programming? (iOS 13+)
  • Combine is Apple's declarative framework for handling events over time. It provides a way to process values asynchronously by combining event-handling operators. It's used for reactive programming, handling asynchronous operations, and managing complex data flows (e.g., network responses, UI events, timers). Key components include Publishers, Operators, and Subscribers.
What is `async/await` in Swift? What problem does it solve? (Swift 5.5+)
  • `async/await` is a modern Swift concurrency feature that simplifies writing asynchronous code. It allows you to write asynchronous code that looks and behaves more like synchronous code, making it easier to read, write, and reason about. It solves the "callback hell" problem often encountered with nested completion handlers. `async` marks a function that can perform asynchronous work, and `await` pauses the execution until an asynchronous operation completes.
Explain the difference between a Struct and a Class in terms of memory allocation. (Revisited)
  • Structs: Value types, typically allocated on the stack. Copies are made when passed or assigned.
  • Classes: Reference types, allocated on the heap. References to the same instance are passed or assigned. Memory is managed by ARC.
What is the difference between a View Controller and a Scene Delegate? (iOS 13+)
  • ViewController: Manages a single screen or a part of the UI within an app.
  • Scene Delegate (`UISceneDelegate`): Manages the lifecycle of a single instance of your app's UI (a "scene"). Introduced in iOS 13 to support multiple windows/scenes on iPadOS and macOS Catalyst. Handles scene-specific lifecycle events (connecting, disconnecting, entering/exiting foreground/background). The `AppDelegate` still handles application-wide events and setup.
What is Core Animation?
  • Core Animation is a powerful compositing engine used by UIKit and SwiftUI to create smooth animations and visual effects. It works with layers (`CALayer`) and provides a high-performance way to animate layer properties (position, opacity, scale).
What is the difference between a `UIView` and a `CALayer`?
  • A `UIView` is a high-level object that handles drawing, event handling (touches), and managing a view hierarchy. Each `UIView` has an associated `CALayer` that manages the visual content and geometry. `CALayer` is a lower-level object primarily focused on drawing and animation.
What is the Responder Chain? How does event handling work?
  • The Responder Chain is a series of objects (responders) that an event (like a touch or motion event) passes through until it is handled. Responders are objects that can respond to events (e.g., `UIView`, `UIViewController`, `UIApplication`). If a responder doesn't handle an event, it passes it to the next responder in the chain. This allows for flexible event handling and delegation.
What is a Gesture Recognizer? How is it used?
  • A Gesture Recognizer is an object that detects specific gestures (taps, swipes, pinches, pans) in one or more views. You create a gesture recognizer instance, configure it, and add it to a view using `addGestureRecognizer(_:)`. The gesture recognizer reports detected gestures to a target object (usually a View Controller) via an action method.
What is Segue? What are the different types of Segues? (UIKit/Storyboards)
  • A Segue is a transition between two View Controllers in a Storyboard. It defines how one screen leads to another. Types include:
    • Show (Push): Pushes a new view controller onto the navigation stack.
    • Present Modally: Presents a view controller over the current content.
    • Custom: Defines a custom transition animation.
    • Unwind: Navigates back through one or more segues to a specific view controller.
How do you pass data between View Controllers using Segues? (UIKit/Storyboards)
  • You implement the `prepare(for:sender:)` method in the source View Controller. Inside this method, you can access the destination View Controller and set its properties with the data you want to pass.
What is Dependency Injection? Why is it important?
  • Dependency Injection (DI) is a design pattern where an object's dependencies (other objects it needs to function) are provided to it from the outside, rather than the object creating them itself. It's important because it:
    • Makes code more modular and testable.
    • Reduces coupling between components.
    • Allows for easier swapping of dependencies (e.g., using mock objects for testing).
What is a Protocol-Oriented Mock? (Testing)
  • A Protocol-Oriented Mock is a mock object created by creating a class or struct that conforms to a specific protocol and implements the protocol's requirements in a way that simulates the behavior of the real implementation for testing purposes. This is a common practice in POP for testing components that rely on dependencies defined by protocols.
What is Test-Driven Development (TDD)?
  • TDD is a software development process where you write automated tests *before* writing the code that needs to be tested. The cycle is: Red (write a failing test), Green (write just enough code to make the test pass), Refactor (improve the code while ensuring tests still pass).
What is Continuous Integration (CI)? How is it relevant to iOS development?
  • CI is a development practice where developers frequently integrate their code changes into a shared repository, and automated builds and tests are run to detect integration issues early. It's relevant to iOS development for automating builds, running tests, and detecting problems quickly. Tools like Xcode Cloud, Jenkins, CircleCI, GitHub Actions, etc., are used for CI.
What is Continuous Delivery (CD)? How is it relevant to iOS development?
  • CD is an extension of CI where code changes that pass automated tests are automatically prepared for release to production. It ensures that your app is always in a deployable state. In iOS, this might involve automating the archiving, signing, and even submission process.
What is the difference between a Bundle ID and an App ID?
  • Bundle ID: A unique identifier for a specific build of your app (e.g., `com.yourcompany.yourapp`). It's set in your Xcode project and is used by the system and the App Store to identify your app.
  • App ID: A two-part string used to identify one or more apps from a single development team. It consists of a Team ID and a Bundle ID (which can be a specific ID or a wildcard). App IDs are managed in your Apple Developer account and are associated with capabilities (like Push Notifications, iCloud).
What is a Provisioning Profile? What is its purpose?
  • A Provisioning Profile is a collection of digital entities that connect developers and devices to a development team and enables a device to be used for testing. It contains:
    • Your team's signing certificate.
    • The App ID of the app.
    • The list of devices allowed to run the app (for development/ad hoc).
  • The purpose is to allow your app to run on specific devices and access certain services based on your developer account and certificates.
Explain Code Signing in iOS development. Why is it necessary?
  • Code Signing is a security measure where Apple verifies that your app is from a known and trusted source and has not been tampered with. It's necessary for distributing apps on the App Store, for enterprise distribution, and even for testing on physical devices. It involves using signing certificates and provisioning profiles.
What is the difference between a Development Certificate and a Distribution Certificate?
  • Development Certificate: Used to sign apps for development and testing on registered devices.
  • Distribution Certificate: Used to sign apps for distribution through the App Store (App Store Distribution) or within an enterprise (Enterprise Distribution).
What is the purpose of the Info.plist file?
  • The Info.plist (Information Property List) file is a structured file that contains essential configuration information about your app, such as its bundle ID, version number, required device capabilities, permissions requested (e.g., access to photos, location), and other system-level settings.
What are Capabilities (or Entitlements) in iOS? How are they configured?
  • Capabilities are special permissions or services that your app can use, such as Push Notifications, iCloud, App Groups, Sign In with Apple, etc. They are configured in the "Signing & Capabilities" section of your Xcode project and are associated with your App ID and Provisioning Profile in your Apple Developer account.
What is an App Group? When would you use it?
  • An App Group is a capability that allows multiple apps (developed by the same team) and their extensions (like widgets, share extensions) to share access to a common container directory on the device. You would use it to share data (e.g., User Defaults, files) between your main app and its extensions.
What is a Widget in iOS 14+? How is it different from a Today Extension?
  • Widgets (using WidgetKit) are small, glanceable views of your app's content that can be placed on the Home Screen or in the Today View. They are designed for displaying timely information and are not interactive in the same way as app extensions. Today Extensions were limited to the Today View and had more limited capabilities. Widgets are built using SwiftUI and have different lifecycle and update mechanisms.
What is an App Clip? When would you use it? (iOS 14+)
  • An App Clip is a small part of your app that can be discovered and launched quickly to perform a specific task, without requiring the user to download the full app from the App Store. You would use it for tasks that are needed immediately in a specific context (e.g., paying for parking, ordering food, renting a scooter).
What is Core ML? How can you integrate machine learning models?
  • Core ML is a framework that allows you to integrate machine learning models into your app. You can use pre-trained models or train your own. Core ML provides APIs to load models, make predictions, and integrate with other frameworks like Vision (for image analysis) and Natural Language (for text analysis).
What is ARKit? What is its purpose?
  • ARKit is Apple's framework for creating Augmented Reality experiences on iOS devices. It uses the device's camera and motion sensors to track the user's movement and position in the real world, allowing you to place and interact with virtual objects in the real environment.
What is SpriteKit? When would you use it?
  • SpriteKit is a 2D graphics rendering and animation framework for creating games and other graphics-intensive applications. You would use it for building 2D games, animated interfaces, or applications with complex visual effects.
What is SceneKit? When would you use it?
  • SceneKit is a 3D graphics rendering and animation framework for creating 3D games and visualizations. You would use it for building 3D games, creating 3D models and scenes, or adding 3D elements to your UI.
What is Metal? When would you use it?
  • Metal is a low-level, high-performance graphics and compute API for Apple platforms. It provides direct access to the GPU, allowing for highly optimized rendering and parallel computation. You would typically use Metal for demanding graphics applications, games engines, or compute-intensive tasks where maximum performance is required, rather than for standard UI development.
What is the difference between a Weak IBOutlet and a Strong IBOutlet?
  • When connecting UI elements from Interface Builder to your code, you typically use `IBOutlet`. By default, these connections are strong. However, for outlets to subviews within a View Controller's view hierarchy, it's often recommended to use `weak` outlets. This is because the view hierarchy itself holds a strong reference to its subviews. Using a strong outlet from the View Controller to a subview can create a retain cycle if the View Controller's view is removed from the hierarchy but the View Controller still holds a strong reference to the subview. Using `weak` prevents this.
What is the difference between a Synchronous and an Asynchronous Network Request? (Revisited)
  • Synchronous: The current thread waits for the network request to complete before proceeding. Can block the main thread and freeze the UI. Should be avoided on the main thread.
  • Asynchronous: The request is started on a background thread, and the current thread continues executing. A completion handler is called when the request finishes. This is the standard approach for network requests in iOS to keep the UI responsive.
What is Method Swizzling in Objective-C? Is it possible in Swift? (Optional)
  • Method Swizzling is a technique in Objective-C Runtime that allows you to swap the implementation of two methods at runtime. It's often used for debugging, logging, or modifying framework behavior. While possible in Swift for methods exposed to the Objective-C runtime (`@objc dynamic`), it's generally discouraged due to its complexity and potential for unintended side effects.
What is Dynamic Dispatch? How does Swift handle it?
  • Dynamic Dispatch is the process of determining which implementation of a method to call at runtime, rather than at compile time. This is essential for polymorphism and inheritance.
    • Classes: Use dynamic dispatch for method calls by default, unless the method is marked as `final`.
    • Structs and Enums: Use static dispatch (calls are resolved at compile time) by default, as they do not support inheritance.
What is Static Dispatch? How does Swift handle it?
  • Static Dispatch is the process of determining which implementation of a method to call at compile time. It's faster than dynamic dispatch. Swift uses static dispatch for structs, enums, and methods marked as `final` in classes.
What are Access Control Levels in Swift? (e.g., `open`, `public`, `internal`, `fileprivate`, `private`)
  • Access Control restricts access to parts of your code from other source files and modules.
    • `open`: Accessible and subclassable outside the defining module.
    • `public`: Accessible outside the defining module, but not subclassable (except within the defining module).
    • `internal` (default): Accessible within the defining module.
    • `fileprivate`: Accessible within the defining source file.
    • `private`: Accessible only within the defining declaration.
What is a Type Alias? Provide an example.
  • A Type Alias gives an existing type a new name. It doesn't create a new type; it just provides an alternative name for an existing one.
    
    typealias Coordinate = (x: Int, y: Int)
    let origin: Coordinate = (0, 0)
            
What is a Tuple? Provide an example.
  • A Tuple groups multiple values into a single compound value. The values within a tuple can be of any type and do not need to be of the same type.
    
    let http404Error = (statusCode: 404, description: "Not Found")
    print("The status code is \(http404Error.statusCode)")
            
What is the difference between `Array`, `Set`, and `Dictionary` in Swift?
  • Array: An ordered collection of values of the same type. Elements are accessed by their index. Allows duplicate values.
  • Set: An unordered collection of unique values of the same type. Elements must be hashable. Efficient for checking membership.
  • Dictionary: An unordered collection of key-value pairs. Keys are unique and must be hashable. Values are accessed by their key.
What is the purpose of Guard Statement?
  • A `guard` statement is used for early exit from a function, loop, or conditional statement if a condition is not met. It's often used for validating conditions at the beginning of a function. If the condition in a `guard` statement is false, the `else` block is executed, which must exit the current scope (`return`, `break`, `continue`, or `throw`). It also allows you to safely unwrap optionals and use the unwrapped value after the `guard` statement.
What is the difference between `if let` and `guard let`?
  • `if let`: Safely unwraps an optional and executes the code inside the `if` block only if the optional has a value. The unwrapped value is only available within the `if` block.
  • `guard let`: Safely unwraps an optional. If the optional has a value, the unwrapped value is available *after* the `guard` statement in the current scope. If the optional is `nil`, the `else` block is executed, which must exit the current scope. `guard let` is preferred for checking prerequisites at the start of a function.
What is the difference between `map`, `filter`, and `reduce` on collections?
  • `map`: Transforms each element of a collection using a closure and returns a new array containing the transformed elements.
  • `filter`: Returns a new array containing only those elements from a collection for which a closure returns `true`.
  • `reduce`: Combines all elements in a collection into a single value, using an initial value and a combining closure.
What is the purpose of the `defer` statement?
  • The `defer` statement is used to execute a block of code just before the current scope is exited, regardless of how the exit occurs (e.g., via `return`, `throw`, or reaching the end of the scope). It's often used for cleanup tasks like closing files or releasing resources.
What is a Property Observer vs. a Computed Property? (Revisited)
  • Property Observer: Executed *before* (`willSet`) or *after* (`didSet`) a stored property's value changes. They don't store a value themselves but react to changes in a stored property.
  • Computed Property: Calculates its value every time it's accessed. It doesn't store a value directly but provides a getter and optionally a setter.
Explain the concept of Memory Leaks in iOS.
  • A Memory Leak occurs when objects are allocated in memory but are no longer accessible or needed by the application, yet ARC cannot deallocate them because there are still strong references pointing to them. Strong reference cycles are a common cause of memory leaks.
How do you debug Memory Leaks in Xcode?
  • Using the Xcode Debug Navigator to monitor memory usage.
  • Using the Instruments tool, specifically the Leaks template, to detect and identify memory leaks.
  • Using the Debug Memory Graph feature in Xcode to visualize object relationships and identify strong reference cycles.
What is the difference between `==` and `===` in Swift?
  • `==`: Checks for *equality* of value. Compares the content of two objects.
  • `===`: Checks for *identity* (reference equality). Determines if two references point to the exact same instance in memory (only applicable to class instances).
What is Protocol Conformance? How is it indicated?
  • Protocol Conformance means that a class, struct, or enum satisfies the requirements defined by a protocol. It's indicated by listing the protocol name after the type name, separated by a colon (e.g., `class MyClass: SomeProtocol`). If conforming to a superclass, the superclass name comes first.
What is the purpose of the `AnyObject` protocol?
  • The `AnyObject` protocol is a protocol that any class type implicitly conforms to. It allows you to write code that can work with any instance of a class. It's similar to `id` in Objective-C.
What is the difference between `Array` and `[Element]`?
  • They are equivalent ways of declaring an array type in Swift. `[Element]` is the preferred shorthand syntax.
What is the difference between `Dictionary` and `[Key: Value]`?
  • They are equivalent ways of declaring a dictionary type in Swift. `[Key: Value]` is the preferred shorthand syntax.
What is the difference between a Constant and a Literal?
  • Constant: A named value that cannot be changed after initialization (declared with `let`).
  • Literal: A hardcoded value written directly in the code (e.g., `10`, `"hello"`, `[1, 2, 3]`).
What is the purpose of the `Codable` protocol? (Revisited)
  • To enable easy encoding and decoding of custom data types to and from external representations like JSON or Property Lists.
What is the difference between `Encodable` and `Decodable`?
  • `Encodable`: A protocol that allows a type to encode itself into an external representation.
  • `Decodable`: A protocol that allows a type to decode itself from an external representation.
  • `Codable` is a type alias for both `Encodable` and `Decodable`.
What is the purpose of the `CodingKeys` enum when using `Codable`?
  • The `CodingKeys` enum is used within a `Codable` type to customize how the properties are mapped to keys in the external representation (e.g., JSON). You list the properties you want to include in the encoding/decoding process and can provide different names for the keys in the external format.
What is a Property Wrapper? Provide another example (not @Clamped). (Revisited)
  • A Property Wrapper encapsulates logic for getting and setting a property's value.
    
    @propertyWrapper
    struct Capitalized {
        private var value: String = ""
    
        var wrappedValue: String {
            get { value }
            set { value = newValue.capitalized }
        }
    }
    
    struct User {
        @Capitalized var name: String = ""
    }
    
    var user = User()
    user.name = "john doe"
    print(user.name) // Prints "John Doe"
            
What is the purpose of the `@State` property wrapper in SwiftUI?
  • `@State` is a property wrapper used in SwiftUI to manage simple, local state within a View struct. When a `@State` property changes, SwiftUI automatically invalidates and redraws the view and its dependencies. It's designed for value types and should be marked as `private`.
What is the purpose of the `@Binding` property wrapper in SwiftUI?
  • `@Binding` is a property wrapper used in SwiftUI to create a two-way connection to a value source. It allows a View to read and write a value owned by another View or source of truth without owning the value itself. Changes to the bound value in one View are reflected in the source and any other Views bound to it.
What is the purpose of the `@ObservedObject` property wrapper in SwiftUI?
  • `@ObservedObject` is a property wrapper used in SwiftUI to observe changes in a reference type (class) that conforms to the `ObservableObject` protocol. When a published property (`@Published`) within the observed object changes, SwiftUI invalidates and redraws the view. Use for complex data models that are shared across multiple views.
What is the purpose of the `@EnvironmentObject` property wrapper in SwiftUI?
  • `@EnvironmentObject` is a property wrapper used in SwiftUI to access a shared object that has been placed in the environment by an ancestor view. It's similar to `@ObservedObject` but is used for objects that are shared throughout a significant portion of the view hierarchy, avoiding the need to pass the object explicitly through initializer parameters. The object must conform to `ObservableObject`.
Explain the difference between `@State`, `@Binding`, `@ObservedObject`, and `@EnvironmentObject`. (SwiftUI)
  • `@State`: Simple, local value type state within a single View.
  • `@Binding`: Two-way connection to a value owned elsewhere. Allows read/write access without ownership.
  • `@ObservedObject`: Observes changes in a reference type (`ObservableObject`) owned by the current View or passed in.
  • `@EnvironmentObject`: Observes changes in a reference type (`ObservableObject`) provided by the environment (an ancestor view). Used for shared data across a view hierarchy.
What is the purpose of the `ObservableObject` protocol and `@Published` property wrapper in SwiftUI/Combine?
  • `ObservableObject`: A protocol that a class conforms to to indicate that it can be observed for changes.
  • `@Published`: A property wrapper used on properties within an `ObservableObject` class. When a `@Published` property changes, it automatically sends a notification to any observers (like `@ObservedObject` or `@EnvironmentObject` in SwiftUI), triggering UI updates.
What is Combine? (Revisited)
  • Combine is a framework for handling asynchronous events by combining publishers and subscribers. It provides operators to transform, filter, and process streams of values over time.
Explain the basic components of Combine: Publisher, Operator, Subscriber.
  • Publisher: Emits values over time. Can be a built-in publisher (like `Timer.publish`) or a custom publisher.
  • Operator: Transforms, filters, or combines values emitted by a publisher. Operators return a new publisher.
  • Subscriber: Receives values from a publisher. Performs actions based on the received values or completion events (success or failure).
What is the purpose of the `.sink` subscriber in Combine?
  • `.sink` is a common subscriber provided by Combine. It allows you to attach closures to a publisher to handle received values and completion events. It's a simple way to react to events from a publisher.
What is the purpose of the `.assign(to:)` subscriber in Combine?
  • `.assign(to:)` is a subscriber that automatically assigns the received values from a publisher to a property of an object. It's often used to bind a publisher's output to a `@Published` property of an `ObservableObject`.
What are Generic Parameters in Swift? Provide an example. (Revisited)
  • Generic Parameters are placeholder types defined within angle brackets (`<>`) that allow functions or types to work with any type while maintaining type safety.
    
    struct Stack {
        private var items = [Element]()
    
        mutating func push(_ item: Element) {
            items.append(item)
        }
    
        mutating func pop() -> Element {
            return items.removeLast()
        }
    }
            
What is the difference between a Protocol and a Generic?
  • Protocol: Defines a contract of behavior that types can conform to. Focuses on what a type *can do*.
  • Generic: Allows functions and types to work with *any* type in a type-safe way. Focuses on making code reusable across different types.
  • They are often used together, for example, a generic function might require its type parameter to conform to a specific protocol (`func process(_ value: T)`).
What is the purpose of the `associatedtype` keyword in Protocols?
  • `associatedtype` is used in a protocol to define a placeholder type name that must be specified by any type conforming to the protocol. It allows the protocol to refer to a type that is part of its definition but is not known until the conforming type provides it.
What is an Opaque Return Type (`some Protocol`) in Swift? (Swift 5.1+)
  • An Opaque Return Type (using the `some` keyword before a protocol) specifies that a function or computed property returns a value of some type that conforms to the given protocol, but it doesn't reveal the specific underlying type. This allows you to return different specific types in different scenarios while still guaranteeing conformance to the protocol, which is common in SwiftUI (e.g., `some View`).
What is the difference between returning `some Protocol` and returning the concrete type?
  • Returning the concrete type (e.g., `-> MyView`) means the function *always* returns an instance of `MyView`.
  • Returning `some Protocol` (e.g., `-> some View`) means the function returns *an instance of some type* that conforms to `View`, but the caller doesn't know or care about the specific concrete type. This is crucial for SwiftUI's performance optimizations and flexibility in building complex view hierarchies.
What is the purpose of the `@main` attribute? (Swift 5.3+)
  • The `@main` attribute is used to indicate the entry point of an executable program. When applied to a struct or class, it automatically synthesizes the necessary boilerplate code (like the `main` function) to start the application. This simplifies the setup, especially for SwiftUI apps (applied to the `App` struct).
What is the difference between a Class and a Struct in terms of identity? (Revisited)
  • Classes: Have identity. Multiple references can point to the same instance. Changes made through one reference are visible through all other references.
  • Structs: Do not have identity in the same way. Each instance is a unique value. When you copy a struct, you get a completely independent copy of the data. Changes to one copy do not affect others.
What is a Value Type vs. a Reference Type? (Revisited)
  • Value Type (Structs, Enums, Tuples, basic types like Int, String, Bool): A copy of the value is created when it's assigned to a new variable or passed to a function. Each variable holds its own unique copy of the data.
  • Reference Type (Classes, Closures): A reference (pointer) to a single instance is copied when it's assigned or passed. Multiple variables can refer to the same instance in memory.
What is the purpose of the `inout` keyword?
  • The `inout` keyword is used in function parameters to indicate that a parameter's value can be modified inside the function, and those changes will persist after the function returns. It effectively passes a reference to the variable, allowing the function to modify the original value.
What is the difference between a `var` parameter and an `inout` parameter?
  • A `var` parameter creates a mutable *copy* of the argument inside the function. Changes made to the parameter inside the function do not affect the original value outside the function.
  • An `inout` parameter allows the function to modify the *original* variable passed as an argument.
What is the difference between a Type Method and an Instance Method? (Revisited)
  • Type Method: Called on the type itself (`MyType.someMethod()`). Defined with `static` or `class`.
  • Instance Method: Called on an instance of the type (`myInstance.someMethod()`).
What is the purpose of the `lazy` keyword?
  • The `lazy` keyword is used for stored properties of a class or struct. A `lazy` property's initial value is not calculated until the first time it is accessed. This is useful for properties whose initial value is computationally expensive or depends on other properties that are not available during initialization.
What is the difference between a Stored Property and a Lazy Stored Property?
  • A Stored Property's value is initialized when the instance is created. A Lazy Stored Property's value is initialized only when it is first accessed.
What is a Mutating Method? When is it required?
  • A Mutating Method is an instance method of a struct or enum that modifies the instance itself or its properties. Because structs and enums are value types, their properties cannot be changed within a method unless the method is explicitly marked with the `mutating` keyword.
What is the purpose of the `didSet` and `willSet` property observers? (Revisited)
  • To observe and react to changes in a stored property's value. `willSet` is called just before the value is set, and `didSet` is called just after the value is set.
What is the difference between an Enum with Raw Values and an Enum with Associated Values?
  • Raw Values: Pre-populated values of the same type for each case of the enum (e.g., `case success = 200`). Useful for mapping cases to specific values like status codes or strings.
  • Associated Values: Allow you to store additional information of varying types alongside each case. The values are determined when you create an instance of the enum case. Useful for representing different states or types of data.
    
    enum APIResult {
        case success(data: Data)
        case failure(error: Error)
    }
            
What is Pattern Matching in Swift? Provide an example.
  • Pattern Matching is a powerful feature used with `switch` statements, `if case let`, and `for case let` to match values against different patterns (e.g., specific values, ranges, types, tuple elements, enum cases with associated values).
    
    enum APIResult {
        case success(data: Data)
        case failure(error: Error)
    }
    
    let result = APIResult.success(data: Data())
    
    switch result {
    case .success(let data):
        print("Success with data: \(data)")
    case .failure(let error):
        print("Failure with error: \(error)")
    }
            
What is the purpose of the `Result` type in Swift? (Swift 5+)
  • The `Result` type is an enum with two cases: `.success(Value)` and `.failure(Error)`. It's used to represent the outcome of an operation that can either succeed and return a value or fail and return an error. It provides a standard way to handle asynchronous operations that can fail, improving code clarity and safety compared to using optionals or throwing errors directly in completion handlers.
How would you handle an asynchronous operation that can succeed or fail using the `Result` type?
  • A function performing the operation would take a completion handler with a `Result` type parameter:
    
    func fetchData(completion: @escaping (Result) -> Void) {
        // ... perform async task ...
        if success {
            completion(.success(fetchedData))
        } else {
            completion(.failure(someError))
        }
    }
    
    // Calling the function
    fetchData { result in
        switch result {
        case .success(let data):
            // Handle data
        case .failure(let error):
            // Handle error
        }
    }
            
What is the difference between a class and a static method? (Revisited)
  • `static`: Used for type methods and properties in both classes and structs/enums. Cannot be overridden by subclasses.
  • `class`: Used for type methods and computed type properties in classes only. Can be overridden by subclasses.
What is a Protocol Extension? Provide an example. (Revisited)
  • An extension on a protocol to provide default implementations for its requirements or add new functionality.
    
    protocol Identifiable {
        var id: String { get }
    }
    
    extension Identifiable {
        func printID() {
            print("ID: \(id)")
        }
    }
    
    struct User: Identifiable {
        let id: String
        let name: String
    }
    
    let user = User(id: "123", name: "Alice")
    user.printID() // Uses the default implementation
            
What is the purpose of the `where` clause in Swift?
  • The `where` clause is used to specify constraints on associated types in protocols or on generic parameters in functions or types. It's used to add further requirements beyond simple protocol conformance.
    
    func process(_ collection: C) where C.Element: Equatable {
        // ... process collection where elements are Equatable
    }
            
What is a Property Observer vs. a Computed Property? (Revisited)
  • Property Observers (`willSet`, `didSet`) are attached to *stored* properties to react to value changes. Computed properties have no storage and calculate their value on demand.
What is the purpose of the `Codable` protocol? (Revisited)
  • To enable automatic encoding and decoding of types to/from external representations like JSON.
What is the difference between `Encodable` and `Decodable`? (Revisited)
  • `Encodable` allows converting an object into data. `Decodable` allows converting data into an object. `Codable` is both.
What is the purpose of the `CodingKeys` enum? (Revisited)
  • To customize how property names map to keys in the encoded/decoded data.
What is a Property Wrapper? Provide an example. (Revisited)
  • Reusable logic for managing a property's value. `@State`, `@Binding`, `@Published` are examples.
Explain the difference between `@State`, `@Binding`, `@ObservedObject`, and `@EnvironmentObject`. (SwiftUI) (Revisited)
  • @State: Local, simple value state.
  • @Binding: Two-way reference to state owned elsewhere.
  • @ObservedObject: Observes a reference type (`ObservableObject`) owned by the view or passed in.
  • @EnvironmentObject: Observes a shared `ObservableObject` provided by an ancestor view in the environment.
What is the purpose of the `ObservableObject` protocol and `@Published` property wrapper? (Revisited)
  • `ObservableObject` marks a class that can be observed. `@Published` marks properties within that class that will notify observers when they change.
What is Combine? (Revisited)
  • Framework for handling asynchronous events with publishers, operators, and subscribers.
Explain the basic components of Combine: Publisher, Operator, Subscriber. (Revisited)
  • Publisher: Emits values. Operator: Transforms values. Subscriber: Receives values and acts on them.
What is the purpose of the `.sink` subscriber? (Revisited)
  • To attach closures to handle values and completion events from a publisher.
What is the purpose of the `.assign(to:)` subscriber? (Revisited)
  • To automatically assign values from a publisher to a property.
What are Generic Parameters? (Revisited)
  • Placeholder types that allow functions/types to work with any type in a type-safe way.
What is the difference between a Protocol and a Generic? (Revisited)
  • Protocol: Defines capabilities. Generic: Enables reusable code across types.
What is the purpose of `associatedtype`? (Revisited)
  • Defines a placeholder type within a protocol that conforming types must specify.
What is an Opaque Return Type (`some Protocol`)? (Revisited)
  • Indicates a function returns a value of *some* type conforming to a protocol, without revealing the specific type.
What is the purpose of the `@main` attribute? (Revisited)
  • Marks the entry point of the program, automatically generating boilerplate code.
What is the difference between a Class and a Struct in terms of identity? (Revisited)
  • Classes have identity (reference semantics). Structs are value types (copy semantics).
What is a Value Type vs. a Reference Type? (Revisited)
  • Value types are copied on assignment/pass. Reference types share a single instance via references.
What is the purpose of the `inout` keyword? (Revisited)
  • Allows a function to modify the original variable passed as an argument.
What is the difference between `var` and `inout` parameters? (Revisited)
  • `var` copies the value; `inout` passes a reference.
What is the difference between a Type Method and an Instance Method? (Revisited)
  • Type methods are called on the type. Instance methods are called on an instance.
What is the purpose of the `lazy` keyword? (Revisited)
  • Delays the initialization of a stored property until its first access.
What is a Mutating Method? (Revisited)
  • An instance method in a struct/enum that modifies the instance itself.
What is the difference between an Enum with Raw Values and an Enum with Associated Values? (Revisited)
  • Raw Values: Pre-defined values for cases. Associated Values: Data attached to specific case instances.
What is Pattern Matching? (Revisited)
  • Matching values against patterns using `switch`, `if case let`, etc.
What is the purpose of the `Result` type? (Revisited)
  • Represents the outcome of an operation that can succeed or fail with an error.
How would you handle an asynchronous operation that can succeed or fail using the `Result` type? (Revisited)
  • Use a completion handler with `(Result) -> Void`.
What is the difference between a class and a static method? (Revisited)
  • `class` methods can be overridden; `static` methods cannot.
What is a Protocol Extension? (Revisited)
  • Adds default implementations or new functionality to a protocol.
What is the purpose of the `where` clause? (Revisited)
  • Adds constraints to associated types or generic parameters.