Skip to main content

Swift engineer technical fundamentals interview questions

12 questions on technical fundamentals for swift engineer candidates. Expect prompts such as “Debug a retain cycle in Swift” and “Explain Swift's access control levels”, each with a worked answer outline and the follow-ups interviewers push on.

Questions

Showing 1 to 12 of 12 technical fundamentals questions.

As asked

An iOS screen is dismissed but its view model and network task never deallocate. How would you find and fix the retain cycle?

Sample answer outline

Start with the memory graph debugger or Instruments to identify the ownership chain keeping the object alive. Common causes are closures capturing self strongly, delegates not marked weak, Combine subscriptions retained by the same object they capture, and tasks that outlive the view lifecycle. The fix is not blindly adding weak self everywhere, but deciding which object owns the work and when cancellation should happen. A view model should usually cancel outstanding tasks in deinit or when the lifecycle ends. Strong candidates explain ARC as deterministic reference counting with cycles that need explicit weak or unowned links.

Expect these follow-ups

  • When is unowned safe and when is it dangerous?
  • How do async Task closures capture self?
  • How would you test that a screen deallocates?
arcmemoryios

As asked

List Swift's access control modifiers from most restrictive to least, explain what each means, and give an example of when you would choose internal versus public versus open for a framework type.

Sample answer outline

A strong answer lists private (enclosing declaration), fileprivate (enclosing file), internal (module, the default), public (visible outside module, non-subclassable), open (visible and subclassable outside module). Framework example: public for a struct the consumer uses, open for a view controller they are expected to subclass, internal for helpers. Candidate should note that Swift's default is internal and that frameworks must explicitly expose public API.

Expect these follow-ups

  • What is the difference between private and fileprivate in practice?
  • Can you override a public method in a subclass outside the defining module?
swiftaccess-controlmodulesfundamentalslanguage

As asked

Explain what associated values on Swift enums allow you to do that a simple enum or struct cannot. Give a concrete iOS example and show how you would pattern-match on them in a switch statement.

Sample answer outline

A strong answer explains that associated values attach typed payloads to specific cases, enabling sum types (algebraic data types), and contrasts with Java or C enums that cannot. Example: Result<Success, Failure> or a NetworkState enum with .loading, .success(Data), .failure(Error). Pattern matching syntax shown with let binding in a switch case. Candidate should mention indirect enum for recursive types.

Expect these follow-ups

  • How does an enum with associated values differ from a protocol with multiple conforming types in terms of exhaustiveness?
  • What is the RawRepresentable protocol and when can an enum have both a RawValue and associated values?
swiftenumspattern-matchingfundamentalstype-system

As asked

Explain how Swift closures capture variables from their enclosing scope. What is the difference between capturing by reference and by value, and how does the capture list syntax change capture semantics?

Sample answer outline

A strong answer explains that closures capture reference to variables (not copies), so a closure that captures an Int still sees mutations because the variable box is captured, not the value at the time of closure creation. The capture list [x] copies x at closure creation time. For reference types, [weak self] and [unowned self] change ownership. Candidate should give a bug example where a counter inside a loop is captured by reference and all closures see the final value.

Expect these follow-ups

  • What happens if you capture a value type with a capture list and then mutate the original after the capture?
  • Why do escaping closures require explicit self in the capture list in Swift?
closuresswiftmemorycapture-listfundamentals

As asked

Explain the delegation pattern as used throughout UIKit and Foundation. Why did Apple choose delegation over inheritance or direct callbacks for things like UITableViewDelegate and URLSessionDelegate?

Sample answer outline

A strong answer defines delegation as an object conforming to a protocol being assigned to handle a set of callbacks on behalf of another object, which keeps the framework class single-purpose and allows the caller to provide custom behavior without subclassing. Benefits over inheritance: avoids deep hierarchies, allows a single object to delegate multiple unrelated objects, and is more testable (mock the delegate). Compared to blocks: cleaner for many callbacks on one object.

Expect these follow-ups

  • What is the risk if a delegate property is declared strong instead of weak?
  • How does Swift protocol extensions let you provide default delegate implementations without breaking existing conformers?
delegationuikitprotocolsfundamentalsios

As asked

Explain UITableView's cell reuse mechanism, why it exists, and describe three specific bugs that result from misunderstanding it, each with its fix.

Sample answer outline

A strong answer explains the reuse queue recycles off-screen cells to avoid instantiating expensive views per row. Bugs: 1) stale state (a cell configured for row 3 shows checkmark when reused for row 10 because checkmark was not reset in configureCell, fix: always set all visual state in cellForRowAt), 2) image flickering from async image loading finishing and setting on a recycled cell that now shows a different row (fix: cancel previous download on prepareForReuse), 3) wrong font after dynamic type change on cached cells (fix: apply font in configureCell or observe UIContentSizeCategory changes).

Expect these follow-ups

  • How does DiffableDataSource change how you call reloadData and what flicker does it eliminate?
  • When would you create a completely custom cell dequeue mechanism instead of using dequeueReusableCell?
uitableviewuikitcell-reusefundamentalsios

As asked

Explain the difference between the main queue, global concurrent queues, and custom serial queues in GCD. When would you create a custom serial queue versus using a global concurrent queue?

Sample answer outline

A strong answer covers: main queue is a serial queue on the main thread (all UI work), global concurrent queues are thread-pool backed with QoS levels (userInteractive, userInitiated, utility, background), and custom serial queues execute tasks in FIFO order on one thread at a time (useful for thread-safe access to a shared resource without locks). Choose custom serial when you need guaranteed ordering or mutual exclusion; choose global concurrent when tasks are independent and you want maximum throughput.

Expect these follow-ups

  • What is QoS inversion and when can it cause a main thread stall?
  • How does DispatchQueue.sync differ from async and what deadlock does sync on the current queue cause?
gcdconcurrencyqueuesswiftfundamentals

As asked

Explain how Swift structured concurrency handles cancellation, actor isolation and UI updates in an iOS app.

Sample answer outline

Structured concurrency ties async child tasks to a parent task so cancellation and errors can propagate through the task tree. Cancellation is cooperative, so long-running work must check Task.isCancelled or call throwing APIs that observe cancellation. UI state should be updated on the MainActor, either by marking the view model or specific methods. Actors protect mutable state through isolation, but they do not make blocking or slow code free. Candidates often overstate cancellation as preemptive or forget that detached tasks leave the structured tree.

Reference implementation (swift)

Swift
@MainActor
final class ProfileViewModel: ObservableObject {
    @Published private(set) var state: State = .idle

    func load(id: String) async {
        state = .loading
        do {
            let profile = try await api.fetchProfile(id: id)
            try Task.checkCancellation()
            state = .loaded(profile)
        } catch is CancellationError {
            state = .idle
        } catch {
            state = .failed(error)
        }
    }
}

Expect these follow-ups

  • When would you use Task.detached?
  • What does @MainActor guarantee and what does it not guarantee?
  • How do actors avoid data races without locks?
concurrencymainactorcancellation

As asked

What data is UserDefaults appropriate for, what are its performance and size limitations, and what are three things you should never store in it?

Sample answer outline

A strong answer explains UserDefaults is appropriate for small key-value preferences (theme, last search query, simple flags), that Apple recommends keeping under ~512KB (no hard limit but larger serializes slowly), and that reads on app launch block if the plist is large. Should never store: sensitive credentials (not encrypted), large binary blobs (images, full data models), or frequently changing data that would cause constant plist re-serialization.

Expect these follow-ups

  • How does UserDefaults work with App Groups for sharing data with a widget extension?
  • What is Suite-based UserDefaults and when do you use it?
userdefaultsstorageiosfundamentalspreferences

As asked

What are the most common bugs developers introduce when using NotificationCenter in iOS apps, and how do you avoid each one?

Sample answer outline

A strong answer names: forgetting to remove an observer causing a crash when a notification fires on a deallocated object (mitigated by block-based observation with a stored token that deregisters on dealloc), observing on the wrong thread (background thread posting to observers that update UI), duplicate observers from adding the same observer twice without removing (causes the handler to fire twice), and using overly broad notification names that couple unrelated modules.

Expect these follow-ups

  • How does the block-based NotificationCenter.addObserver(forName:object:queue:using:) avoid the remove-observer requirement of the selector-based API?
  • What would you use instead of NotificationCenter for communicating between a ViewModel and a View?
notificationcenteriosfundamentalsbugsthread-safety

As asked

When would you choose UICollectionView over UITableView for a list, and when is UITableView still the better choice? What does UICollectionView's compositional layout add over flow layout?

Sample answer outline

A strong answer says UITableView is simpler for one-column flat or grouped lists with standard cells, section headers, and swipe actions already built in. UICollectionView is better for grids, multi-column layouts, horizontal scrolling, or any layout beyond a simple list. Compositional layout (iOS 13) adds declarative section, group, and item sizing with orthogonal scrolling per section, making complex App Store-style layouts feasible without custom layout subclasses.

Expect these follow-ups

  • How do you implement a collapsing section header in UICollectionView with diffable data source?
  • What is the List configuration in UICollectionView compositional layout and how does it compare to UITableView?
uitableviewuicollectionviewuikitfundamentalslayout

As asked

Describe the iOS app sandbox, the main file system containers available to an app, and which directories survive backup, app updates, and iOS upgrades.

Sample answer outline

A strong answer names the container structure: Bundle (read-only app resources), Documents (user data, backed up by iCloud/iTunes, survives update), Library/Caches (re-creatable cache, not backed up, may be purged by OS), Library/Application Support (app data that is not user-facing, backed up, survives update), Library/Preferences (UserDefaults lives here, backed up), tmp (temporary, not backed up, purged on reboot). Candidate should mention setting NSURLIsExcludedFromBackupKey for large caches.

Expect these follow-ups

  • What happens to a file stored in Documents if the user upgrades iOS on the device?
  • How do you share files between your app and a document provider extension?
iossandboxfile-systemfundamentalsstorage