Skip to content
tezvyn:

Top 30 Intermediate iOS & Swift Interview Questions and Answers

30 intermediate multiple-choice iOS & Swift interview questions, past the definitions: how the pieces fit together, what breaks in practice, and the trade-off behind a choice. They come from 30 bites in the iOS & Swift library, the middle slice of the 129 iOS & Swift interview questions in the library. 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.

SwiftUI, UIKit, Xcode, Swift language, Apple platforms

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

    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

  2. Question 2 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?

  3. Question 3 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?

  4. Question 4 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].

  5. Question 5 of 30

    Which approach correctly creates a reusable Staging workflow without hardcoding environment details in Swift?

    Show the answer

    Answer: a · Duplicate the app scheme, create a Staging build configuration, pair them in the scheme editor, add the API URL as a launch environment variable, and share the scheme.

    A scheme orchestrates which build configuration to use and can inject runtime values via the Arguments tab; duplicating and sharing it to xcshareddata creates a reusable workflow without code changes. Option D misapplies SWIFT_ACTIVE_COMPILATION_CONDITIONS, which is a compile-time flag, not a mechanism for runtime environment variables like an API URL.

    Read the full bite: What is an Xcode Scheme? How do you configure a custom one?

  6. Question 6 of 30

    Why does a symbolic breakpoint on UIViewAlertForUnsatisfiableConstraints help debug Auto Layout in UIKit?

    Show the answer

    Answer: c · It resolves to a runtime address without needing UIKit source code and lets you trace back to your code

    A symbolic breakpoint stops on a function by name inside closed-source UIKit without requiring source code, and the backtrace reveals which of your methods added the conflicting constraints. Distractor D is tempting because both breakpoints halt execution, but exception breakpoints catch all thrown exceptions broadly, whereas a symbolic breakpoint is precisely targeted to a specific function entry.

    Read the full bite: Explain symbolic breakpoints and debug Auto Layout with one

  7. Question 7 of 30

    You are investigating rhythmic frame drops during table view scrolling. Which profiling strategy best isolates the specific subsystem causing the hitches?

    Show the answer

    Answer: c · Record with the Core Animation instrument to find hitch spikes, then cross-reference Time Profiler on the main thread during those frame boundaries

    Core Animation reveals frame-level hitch ratios and exact frame boundaries, while Time Profiler pinpoints main-thread blocking work during those frames; print statements lack frame precision and alter performance, while Leaks and raw CPU metrics do not correlate specific frames to code paths.

    Read the full bite: Which Instrument diagnoses scroll stuttering and dropped frames?

  8. Question 8 of 30

    When does UIKit allocate a new table or collection view cell during scrolling?

    Show the answer

    Answer: c · When the reuse pool has no cell with the requested identifier

    UIKit only creates a new cell when the reuse pool cannot supply one matching the requested identifier; the tempting belief that a new instance is created for every visible row ignores that scrolling primarily recycles existing cells.

    Read the full bite: How do UITableView and UICollectionView reuse cells?

  9. Question 9 of 30

    Which statement accurately describes a key architectural difference between UIKit Auto Layout and SwiftUI?

    Show the answer

    Answer: b · UIKit uses an external constraint solver while SwiftUI uses parent-child two-pass size negotiation.

    UIKit Auto Layout depends on an external solver to resolve linear equation constraints into frames, while SwiftUI layout is driven by an internal two-pass size negotiation between parent and child. Option C represents a common misconception; SwiftUI does not wrap or compile down to Auto Layout constraints but instead uses its own compositional layout engine.

    Read the full bite: Compare UIKit Auto Layout and SwiftUI layout systems

  10. Question 10 of 30

    A child view receives an ObservableObject from its parent, must update when it publishes changes, and must not manage its lifecycle. Which wrapper fits?

    Show the answer

    Answer: d · @ObservedObject, because the child receives a reference-type object it does not own

    @ObservedObject is correct because the child gets an externally created ObservableObject and must react to its updates without taking ownership. @Binding is tempting because the data comes from the parent, but it is meant for value types, not reference-type ObservableObjects.

    Read the full bite: Differences between @State, @Binding, @ObservedObject, and @EnvironmentObject

  11. Question 11 of 30

    When wrapping a delegate-based UIKit view for use in SwiftUI, what is the correct way to handle callbacks and avoid retain cycles?

    Show the answer

    Answer: a · Provide a Coordinator object via makeCoordinator and use it as the delegate

    A Coordinator provides a stable reference to handle delegate callbacks without retain cycles. Making the representable struct the delegate is wrong because structs cannot reliably act as reference-type delegates and it introduces mutability and lifecycle issues.

    Read the full bite: Integrate SwiftUI into UIKit and wrap UIKit for SwiftUI

  12. Question 12 of 30

    In an iOS 13+ app using scenes, which task is appropriately handled by SceneDelegate rather than AppDelegate?

    Show the answer

    Answer: c · Restoring user interface state for a specific window session

    SceneDelegate owns per-window state restoration and UI lifecycle, whereas AppDelegate manages process-wide singletons and events. Option B is tempting because it occurs in the background, but silent pushes are process-level and must be handled by AppDelegate.

    Read the full bite: How do AppDelegate and SceneDelegate responsibilities differ?

  13. Question 13 of 30

    When refactoring a massive UIKit ViewController to MVVM, which change best demonstrates the architectural shift?

    Show the answer

    Answer: d · The ViewModel transforms model data into presentation state and exposes it for observation, while the ViewController stays thin and handles only view assembly.

    This reflects the core MVVM shift: presentation logic moves into a UIKit-agnostic ViewModel while the ViewController becomes thin. Option B is tempting but wrong because UIKit MVVM does not eliminate the ViewController, and relying solely on KVO signals outdated iOS knowledge.

    Read the full bite: Explain MVVM, its improvements over MVC, and Swift data binding techniques.

  14. Question 14 of 30

    Which approach correctly enables an iOS app to complete a large file download after the user backgrounds the app?

    Show the answer

    Answer: a · Configure a background URLSession with a unique identifier, enqueue a download task, and invoke the saved completion handler after the delegate finishes processing the transfer.

    A background URLSession with a download task allows the system to continue the transfer even when the app is suspended, and you must call the saved completion handler within about 30 seconds after handling delegate messages. The most tempting distractor mixes the correct background session with beginBackgroundTask, but that API only provides a short CPU extension for cleanup and cannot sustain a long-running download.

    Read the full bite: How do you complete a file download after the app backgrounds?

  15. Question 15 of 30

    In a Coordinator hierarchy, why does the AppCoordinator typically store active child coordinators in an array?

    Show the answer

    Answer: a · To keep flow coordinators alive during their lifecycle and allow parent-controlled cleanup when flows complete

    The parent array retains each child coordinator for the duration of its flow and enables cleanup on completion, preventing memory leaks. Option D is tempting but wrong because coordinators decide flow logic; they do not replace UINavigationController or handle transitions directly.

    Read the full bite: How does the Coordinator pattern decouple navigation, and what are its components?

  16. Question 16 of 30

    Which statement accurately describes the Coordinator pattern's primary purpose in an MVC architecture?

    Show the answer

    Answer: c · It moves navigation flow and view controller creation out of view controllers into dedicated objects

    The coordinator pattern moves navigation flow and view controller creation out of view controllers into dedicated coordinator objects, isolating view controllers for reuse and testing. Claiming that view controllers should still push each other while coordinators only manage the back button is incorrect because navigation logic must be fully extracted, not partially shared.

    Read the full bite: Explain the Coordinator pattern and the navigation problem it solves in MVC

  17. Question 17 of 30

    A modally presented view controller needs to report both Save and Cancel actions back to its parent. Which approach best balances decoupling and memory safety?

    Show the answer

    Answer: c · Define a weak delegate protocol with separate methods for each event, letting any conforming parent handle them without knowing its concrete type.

    A weak delegate protocol with multiple methods keeps the child decoupled from any specific parent and avoids retain cycles, which is ideal for several distinct actions. Option D is tempting but dangerous because strong self captures create a retain cycle: the child holds the closure and the closure holds the parent.

    Read the full bite: Pass data back from a modally presented view controller delegate versus closure

  18. Question 18 of 30

    In a scene-based iOS app, which sequence correctly handles a deep link to an order detail for both cold and warm launches?

    Show the answer

    Answer: a · Handle cold starts in willConnectTo and warm launches in openURLContexts; parse path components with URLComponents and validate the ID before pushing.

    Cold-start URLs arrive in willConnectTo through connectionOptions.urlContexts, while warm launches use openURLContexts, and URLComponents safely parses the path before validating the ID and pushing. The distractor that funnels everything through willConnectTo misses the warm-launch entry point, relies on brittle string splitting, and risks a crash by force-unwrapping the view hierarchy.

    Read the full bite: Handle a deep link URL in SceneDelegate and navigate to order detail.

  19. Question 19 of 30

    To programmatically return to the root of a SwiftUI NavigationStack, what should you modify?

    Show the answer

    Answer: c · The NavigationPath binding owned at or above the root view

    SwiftUI navigation is data-driven, so you clear the bound NavigationPath that serves as the source of truth for the stack depth. Reaching for the underlying UINavigationController breaks the declarative model and reflects a UIKit mindset.

    Read the full bite: How do you pop to root in SwiftUI NavigationStack?

  20. Question 20 of 30

    Why is storing an authentication token in UserDefaults considered insecure even though apps are sandboxed?

    Show the answer

    Answer: d · UserDefaults writes to an unencrypted plist that appears in backups and is readable on jailbroken devices

    UserDefaults persists plain-text to a plist captured in backups and readable on compromised devices, so the sandbox does not protect secrets. It is not shared across apps and the issue is encryption, not size or foreground state.

    Read the full bite: Why store auth tokens in Keychain, not UserDefaults?

  21. Question 21 of 30

    Which pattern safely updates the UI after fetching data on a background Core Data context?

    Show the answer

    Answer: d · Pass NSManagedObjectID values or lightweight structs to the main queue, then use the main context to fetch by ID.

    NSManagedObjects are tied to their context's queue and are not thread-safe, so you must pass only NSManagedObjectID values or plain structs to the main thread and re-fetch by ID on the main context. Passing live NSManagedObjects to the main queue is unsafe because the objects were instantiated on the background context's queue.

    Read the full bite: Describe a pattern for background Core Data fetches and UI updates

  22. Question 22 of 30

    Which schema change requires a heavyweight Core Data migration instead of lightweight automatic migration?

    Show the answer

    Answer: a · Replacing Book's authorName string with a separate Author entity and a relationship

    Promoting a string attribute to a new entity with a relationship is a destructive transform that Core Data cannot infer, forcing a custom mapping model. Renaming with renamingIdentifier is lightweight, so it does not require a heavyweight migration.

    Read the full bite: Describe lightweight vs heavyweight Core Data migration and a heavyweight example

  23. Question 23 of 30

    Which URLSession task should you use to download a large video that must finish even if the user backgrounds the app, and why?

    Show the answer

    Answer: d · A download task on a background session, because it streams to a file and can continue while the app is suspended

    Download tasks stream to disk to avoid exhausting memory and, on a background configuration, continue after suspension with the system relaunching the app. Data tasks buffer in RAM and cannot run in background sessions.

    Read the full bite: URLSession data vs download vs upload tasks

  24. Question 24 of 30

    Two independent network calls are written as let a = try await fetchA() then let b = try await fetchB(). What is the problem and the fix?

    Show the answer

    Answer: d · They run sequentially, doubling latency; use async let for both so they run concurrently, then await together

    Awaiting fetchA before starting fetchB serializes independent work, so total time is the sum. Binding both with async let starts them concurrently, making elapsed time roughly the slower call. await does not auto-parallelize sequential statements.

    Read the full bite: Run two API calls concurrently with async let

  25. Question 25 of 30

    After an awaited URLSession call, why might assigning the result to a @Published property be unsafe without @MainActor isolation?

    Show the answer

    Answer: c · The continuation can resume on a background thread, and UI-bound state must be updated on the main thread

    An awaited call can resume on a background executor, so mutating UI-bound state from there violates the main-thread requirement and risks crashes. @MainActor guarantees the resumption hops back to main; await alone does not.

    Read the full bite: What is @MainActor and why does it matter?

  26. Question 26 of 30

    You set httpAdditionalHeaders on a configuration, but one specific request also sets the same header on its URLRequest. Which value is sent for that request?

    Show the answer

    Answer: c · The per-request value, because request headers override session defaults

    A header set directly on a URLRequest overrides the matching session-level default. The configuration value is only a fallback, so it is not used when the request specifies its own.

    Read the full bite: Add a default header to every URLSession request

  27. Question 27 of 30

    You rotate a square view 45 degrees with a transform, then want to reposition it. Which property should you set, and why?

    Show the answer

    Answer: d · center, because frame is undefined once a non-identity transform is applied

    With a non-identity transform the frame is the bounding box of the rotated view and is documented as undefined to set; use center to reposition. bounds.origin scrolls internal content, not the view's superview position.

    Read the full bite: Difference between frame, bounds, and center

  28. Question 28 of 30

    Which CAShapeLayer property do you animate to make a circular progress ring fill from empty to a given percentage?

    Show the answer

    Answer: d · strokeEnd, animated from 0 to the fraction representing progress

    strokeEnd controls how much of the stroked path is drawn, so animating it from 0 to the progress fraction fills the ring. fillColor fills the interior disc, and rebuilding the path each frame is unnecessary and inefficient.

    Read the full bite: Build a custom circular progress bar in UIKit

  29. Question 29 of 30

    You add a pan and a pinch recognizer to one view but only one ever activates per touch. What is the most likely fix?

    Show the answer

    Answer: d · Implement shouldRecognizeSimultaneouslyWith returning true via the delegate

    By default recognizers are mutually exclusive, so you must implement gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) and return true to let both run. cancelsTouchesInView affects touch delivery to the view, not recognizer coexistence.

    Read the full bite: Allow simultaneous pan and pinch gestures

  30. Question 30 of 30

    Your navigation app stops receiving location updates the moment it is backgrounded, despite the Location background mode being enabled. What is the likely fix?

    Show the answer

    Answer: b · Set allowsBackgroundLocationUpdates to true on the location manager

    The background capability alone is not enough; you must also set allowsBackgroundLocationUpdates = true (with Always authorization) for delivery to continue while backgrounded. Lowering accuracy or downgrading authorization would not restore background updates.

    Read the full bite: Track location continuously in the background

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