Skip to content
tezvyn:

Top 30 Swift Interview Questions and Answers

30 multiple-choice questions on Swift, drawn from 30 bites out of the 201 tagged Swift on Tezvyn. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    A Swift function tries to compile the line let total = 0 followed later in the same function by total = total + 10. What happens?

    Show the answer

    Answer: c · It fails to compile, because let creates a constant that can only be assigned once, and the second line attempts a second assignment

    let enforces single assignment for any type, value or reference, and the compiler catches a second assignment as an error before the program ever runs. Option A is wrong because the let versus var distinction is unrelated to value versus reference semantics, and option C is wrong because Swift never silently ignores a reassignment, it is a hard compile error.

    Read the full bite: Variables and Constants in Swift

  2. Question 2 of 30

    What is the actual effect of declaring a class instance with let in Swift?

    Show the answer

    Answer: c · The reference cannot be reassigned, but the instance's properties can still be mutated

    For reference types, let freezes only the pointer, so the variable cannot be reassigned but the object's properties remain mutable. Option B is a common misconception that confuses the reference with the instance itself.

    Read the full bite: What is the difference between let and var in Swift?

  3. Question 3 of 30

    What is the main benefit of using control flow statements like if and for in Swift?

    Show the answer

    Answer: c · They allow a program to make decisions and repeat specific actions.

    Control flow statements are essential because they enable programs to make decisions based on conditions and to repeat blocks of code, moving beyond a simple linear execution. While they can help structure logic to avoid errors, their primary role isn't automatic error fixing or direct speed optimization.

    Read the full bite: Swift Control Flow: Directing Your Code's Path

  4. Question 4 of 30

    Which statement accurately describes a Swift Optional's implementation and a safe way to unwrap it?

    Show the answer

    Answer: b · It is a generic enum with Some and None cases, and it can be safely unwrapped using if let or the nil-coalescing operator.

    Swift models Optional as a generic enum with Some and None cases, enforcing nil safety at compile time. The most tempting distractor suggests force-unwrapping is standard, but the card warns that using ! is unsafe and only acceptable when non-nil status is guaranteed.

    Read the full bite: What is an optional in Swift? Demonstrate two safe unwrapping methods.

  5. Question 5 of 30

    What is the fundamental mechanism by which Swift Optionals prevent runtime crashes from missing values?

    Show the answer

    Answer: d · They require explicit checks for nil values at compile time, making absence part of the type.

    The card states Optionals make "the potential absence of a value an explicit part of its type system, forcing developers to handle the 'nil' case at compile time." This explicit handling prevents runtime crashes by ensuring nil is addressed before code execution. Force-unwrapping (option C) is explicitly mentioned as an anti-pattern that causes crashes if the value is nil, not prevents them.

    Read the full bite: Swift Optionals: Handling Nothing Safely

  6. Question 6 of 30

    In Swift, a developer omits the default case in a switch over an Int and covers only a few values. What happens?

    Show the answer

    Answer: c · It fails to compile because the switch is not exhaustive

    Swift requires switches to be exhaustive, so covering only some Int values without a default is a compile error. There is no implicit fallthrough and no break is needed, so the other options describe C behavior, not Swift.

    Read the full bite: How does Swift's switch differ from C's switch?

  7. Question 7 of 30

    When designing a Swift data model that requires independent undo snapshots without retroactive mutation, why is a struct preferred over a class?

    Show the answer

    Answer: c · Because assignment creates a unique copy, preventing shared references from mutating prior snapshots.

    Structs are value types, so each assignment copies the instance and prior snapshots remain independent. Option D is a common misconception because structs are not guaranteed to be stack-allocated, and option A is wrong since structs do not support inheritance.

    Read the full bite: Explain the primary differences between a struct and a class in Swift

  8. Question 8 of 30

    When should a developer generally prefer using a Swift struct over a class for a new data type?

    Show the answer

    Answer: b · When the data is simple, self-contained, and changes to a copy should not affect the original.

    Structs are value types, meaning they are copied on assignment, and changes to the copy do not affect the original. This makes them suitable for simple, self-contained data where independent copies are desired. Classes are used for shared identity and inheritance, and are managed by ARC.

    Read the full bite: Swift Structs vs. Classes: Value vs. Reference Types

  9. Question 9 of 30

    You add a new case to a widely-used enum. When does this silently undermine compile-time safety?

    Show the answer

    Answer: b · When switches over the enum include a default clause

    A default clause catches the new case automatically, so the compiler cannot force you to handle it explicitly. Omitting a default clause produces a build error for unhandled cases, which preserves compile-time safety.

    Read the full bite: Swift Enums: Type-Safe Choice Modeling

  10. Question 10 of 30

    Why does indexing a Swift String by an integer like myString[5] not compile, unlike in many other languages?

    Show the answer

    Answer: c · Characters are variable-width grapheme clusters, so an integer offset cannot give O(1) or unambiguous access

    Swift Characters are extended grapheme clusters of varying byte length, so an integer offset is neither constant-time nor meaningful, which is why String.Index is opaque. Immutability is unrelated, and String.Index is not an Int alias.

    Read the full bite: Why can't you subscript a Swift String with an Int?

  11. Question 11 of 30

    What is the primary effect of marking a Swift function parameter with @autoclosure?

    Show the answer

    Answer: a · It wraps the argument expression in a closure so it evaluates lazily only when the function invokes it

    @autoclosure defers evaluation by wrapping the expression in a closure the function may or may not call, as with assert and ??. It does not force eager evaluation, manage retention, or relax type checking.

    Read the full bite: What is @autoclosure and when is it useful?

  12. Question 12 of 30

    Which scenario best justifies using Swift's explicit error handling system (with "throws" and "do-catch")?

    Show the answer

    Answer: d · For operations that can fail in various ways, requiring the caller to understand the specific type of failure to recover.

    The card states Swift's error handling is for "recoverable errors where the caller needs context about what went wrong." Option D directly reflects this, emphasizing the need for specific failure context. Option A is incorrect because the card advises using optionals for simple binary success/failure without extra context.

    Read the full bite: Swift Error Handling: Throwing, Catching, and Propagating

  13. Question 13 of 30

    In performance-critical Swift code, why is 'some Protocol' generally preferred over 'any Protocol'?

    Show the answer

    Answer: b · It guarantees a specific, consistent concrete type at compile time, enabling static dispatch and avoiding existential container overhead.

    The card states that 'any Protocol' incurs performance costs due to dynamic dispatch and potential heap allocation for its existential container. 'some Protocol' avoids this by promising a specific concrete type at compile time, allowing for static dispatch and better performance. Option C is incorrect because protocols do not define stored properties; that is a feature of concrete types or class hierarchies.

    Read the full bite: Protocols: Swift's Blueprint for Behavior

  14. Question 14 of 30

    In Swift, how does declaring an instance with let affect property mutability for a struct compared to a class?

    Show the answer

    Answer: c · With let, a struct is fully immutable, but a class only fixes the reference so its variable properties can still be mutated.

    The card explains that let makes a struct fully immutable, while for a class it only fixes the reference, allowing variable properties to still be mutated. Option B is wrong because it assumes let behaves identically for both, which is a common misconception.

    Read the full bite: Swift struct vs class: differences and when to choose each

  15. Question 15 of 30

    What is the primary issue that "weak" or "unowned" references are designed to resolve in Swift's ARC?

    Show the answer

    Answer: b · Preventing memory leaks caused by two class instances holding strong references to each other.

    The card states that `weak` or `unowned` references are used "To break these cycles" which occur "when two class instances hold strong references to each other, preventing either from ever being deallocated," leading to memory leaks. While `weak`/`unowned` help with deallocation, their primary role is to resolve the specific problem of strong reference cycles, not general unreachability.

    Read the full bite: Automatic Reference Counting (ARC): Swift's Memory Manager

  16. Question 16 of 30

    In Swift, what is a key advantage of providing default behavior through a protocol extension rather than an abstract base class?

    Show the answer

    Answer: d · It enables structs and enums to reuse behavior without being forced into an inheritance hierarchy.

    Protocol extensions let structs and enums gain shared behavior without being forced into an inheritance hierarchy, unlike abstract base classes. They cannot add stored properties, so any answer suggesting they extend state is incorrect.

    Read the full bite: Explain protocols and how extensions provide default implementations

  17. Question 17 of 30

    What is the fundamental behavior of the "await" keyword within an "async" function in Swift?

    Show the answer

    Answer: d · It suspends the current task, allowing the system to use the thread for other pending work.

    The "await" keyword suspends the current task, returning the thread to the system to perform other work until the awaited operation completes. It does not block the thread, which is a common misconception.

    Read the full bite: async/await: Write Concurrent Code That Reads Synchronously

  18. Question 18 of 30

    Why does a stored closure property that references self inside its body cause a memory leak under ARC?

    Show the answer

    Answer: a · Because the instance holds the closure strongly while the closure captures self strongly, preventing deallocation

    The correct answer describes the mutual strong reference that prevents ARC from zeroing out either reference. Option D is a tempting distractor because it plays on the common misconception that closures might be value types, but they are reference types that strongly capture self by default.

    Read the full bite: What is a retain cycle in ARC with closures?

  19. Question 19 of 30

    When a struct and a class instance are independently passed to functions that modify them, which statement accurately describes the effect on the original instances?

    Show the answer

    Answer: b · The original class is modified, but the original struct remains unchanged.

    Structs are value types, so passing them to a function creates a copy, and modifications within the function do not affect the original. Classes are reference types, meaning the function receives a reference to the original instance, so changes made through that reference will modify the original object.

    Read the full bite: Value vs. Reference Semantics in Swift

  20. Question 20 of 30

    When writing a swap function in Swift, what advantage does using a generic placeholder T provide over accepting parameters of type Any?

    Show the answer

    Answer: d · Generics enforce that both parameters are the same concrete type and avoid runtime casting

    Generics preserve compile-time type information, ensuring both arguments share the same type and eliminating unsafe downcasting. Distractor A is tempting because Any permits heterogeneous values, but a generic swap<T> explicitly prevents mixing types, which is exactly why it is type-safe.

    Read the full bite: What are Swift generics, why useful, and write a swap function?

  21. Question 21 of 30

    When is the Swift Result type most advantageous for handling failable operations?

    Show the answer

    Answer: d · When an asynchronous operation needs to explicitly communicate either a success value or a specific error.

    The Result type shines in asynchronous programming, providing a standard and type-safe way to pass either a success value or a specific error, especially when errors cannot be propagated with 'throws' across completion handler boundaries. Option A is incorrect because 'throws' is generally preferred for synchronous functions.

    Read the full bite: The Result Type: Modeling Success and Failure

  22. Question 22 of 30

    Which condition justifies using [unowned self] instead of [weak self] in a Swift closure?

    Show the answer

    Answer: a · The closure is owned by the instance and guaranteed not to execute after deallocation

    [unowned self] is only safe when the closure and instance share identical lifetimes, such as when the instance owns the closure and it cannot execute after deallocation. Option B is tempting because network handlers are common, but they require [weak self] since the user can dismiss the view controller before the response arrives, making unowned unsafe.

    Read the full bite: What is a closure capture list? Explain [weak self] versus [unowned self].

  23. Question 23 of 30

    When implementing Copy-on-Write for a custom Swift struct, what must happen inside a mutating method before modifying the backing reference?

    Show the answer

    Answer: b · Verify isKnownUniquelyReferenced on the backing instance and clone it if the result is false

    Before mutating, you must check isKnownUniquelyReferenced and clone when it returns false, indicating shared ownership. Answer A dangerously inverts the boolean logic, while C and D reflect common misconceptions that either defeat reference sharing or eliminate the optimization entirely.

    Read the full bite: Explain Copy-on-Write in Swift and implement it for custom structs

  24. Question 24 of 30

    Consider a protocol with a default method implementation provided by a protocol extension. If a type conforming to this protocol also implements that same method, which version will be executed?

    Show the answer

    Answer: d · The type's specific implementation will be executed, taking precedence over the default.

    The card explicitly states: "If the conforming type provides its own implementation for a method, the type's specific version is called at runtime, overriding the default." This allows for customization while still providing a fallback. Option A is incorrect because the type's specific implementation takes precedence.

    Read the full bite: Protocol Extensions: Default Behavior for Free

  25. Question 25 of 30

    In Swift structured concurrency, what distinguishes a Task started with Task.init from a child task created via async let?

    Show the answer

    Answer: d · Task.init creates an unstructured task without parent-child cancellation propagation, while async let creates a structured child task

    Task.init creates an unstructured task outside the parent-child tree, whereas async let creates a structured child task bound to its parent's scope and cancellation. Claiming they differ only in syntax repeats the common misconception that async/await is mere syntactic sugar, ignoring the runtime contract of structured concurrency.

    Read the full bite: How does Swift async/await improve on completion handlers?

  26. Question 26 of 30

    In Swift, when is using a capture list with `self` most critical to prevent a retain cycle?

    Show the answer

    Answer: b · When a closure is stored as a property of a class instance and references `self`.

    Option B correctly identifies the scenario where a retain cycle is most likely: when a closure is stored as a property of a class instance and captures `self`. This creates a strong reference from the instance to the closure and from the closure back to the instance. Option A describes a closure that is executed immediately, which does not typically lead to a retain cycle because the closure does not outlive the function call.

    Read the full bite: Retain Cycles and Capture Lists in Swift

  27. Question 27 of 30

    Two threads hold references to the same Swift array through two variables, a and b, and both threads call a mutating method on their variable at the same time without any lock. What is the risk?

    Show the answer

    Answer: c · The isKnownUniquelyReferenced check itself is not thread-safe, so concurrent mutation can race and corrupt the shared buffer

    Copy-on-write's uniqueness check and buffer swap are not synchronized, so two threads racing through them concurrently can corrupt shared state or crash. Arrays are not automatically thread-safe, there is no internal lock making one mutation block for the other, and this is a runtime hazard the compiler cannot catch.

    Read the full bite: Copy-on-Write (CoW) in Swift

  28. Question 28 of 30

    What is the primary reason to open an xcworkspace instead of the underlying xcodeproj when your app depends on a separate framework project?

    Show the answer

    Answer: d · The workspace provides the shared build directory and dependency resolution context

    The workspace establishes a shared build directory and dependency context that lets projects discover each other's products, which an individual project file cannot do. Option C is tempting because it sounds like a higher-level container might replace its contents, but a workspace always contains the underlying project files rather than replacing them.

    Read the full bite: Difference between .xcodeproj and .xcworkspace, and when to use a workspace

  29. Question 29 of 30

    Paused in LLDB with a UIView named header and an Int named count, which commands yield a human-readable view summary and the raw typed integer value?

    Show the answer

    Answer: c · po header and p count

    po header invokes description or debugDescription for a human-readable summary, while p count prints the raw value with type info and creates a persistent variable. Option B is tempting because p is a general evaluator, but it would likely output the UIView's pointer or struct layout instead of its friendly description.

    Read the full bite: What LLDB command prints a UIView description versus an Int?

  30. Question 30 of 30

    What is the primary reason to use an associated type within a Swift protocol?

    Show the answer

    Answer: b · To enable the protocol to refer to a type whose concrete definition is only known by conforming types.

    Associated types exist to allow a protocol's blueprint to refer to a type that is not known until a concrete type adopts the protocol, making the protocol generic over types it uses. Option C is a tempting distractor because, while desirable, the card explicitly states that protocols with associated types cannot be used directly as concrete types for variables or collections without workarounds.

    Read the full bite: Associated Types: Making Protocols Generic

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon