Skip to content

Swift Developer interview questions

100 real questions with model answers and explanations for iOS Developer candidates.

See a Swift Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

let creates an immutable binding; var creates a binding that can change.

  • Prefer let so accidental reassignment is a compiler error.
  • Use var for a counter or total that must change.
  • A let Array cannot append elements; a var Array can.

Why interviewers ask this: This checks the candidate's junior-level understanding of immutability.

type-inference

Swift infers Int from the literal, so no annotation is needed.

  • The inferred type is fixed at compile time.
  • Write : Int64 when an API requires that exact type.
  • A later incompatible assignment remains a compiler error.

Why interviewers ask this: This checks the candidate's junior-level understanding of static type inference.

Swift requires an explicit conversion because narrowing can lose information.

  • Int(3.8) intentionally truncates the fractional part.
  • Check range limits when input may be too large.
  • Convert Int to Double for calculations needing fractions.

Why interviewers ask this: This checks the candidate's junior-level understanding of numeric type safety.

reference-semantics

Value assignment creates an independent value; reference assignment shares one instance.

  • Struct, enum, Array, and Dictionary use value semantics.
  • Class instances have shared reference semantics.
  • Changing one struct copy does not change another copy.

Why interviewers ask this: This checks the candidate's junior-level understanding of value and reference behavior.

copy-on-write

Array copies can share storage until one copy is mutated.

  • Assignment usually avoids an immediate element-by-element copy.
  • The first mutation creates private storage for that copy.
  • Observable behavior still follows value semantics.

Why interviewers ask this: This checks the candidate's junior-level understanding of copy-on-write.

swiftoptionals

An Optional holds either a wrapped value or nil.

  • Int? is shorthand for Optional<Int>.
  • It must be unwrapped where a plain Int is required.
  • It models missing data without sentinel values such as -1.

Why interviewers ask this: This checks the candidate's junior-level understanding of optional values.

swiftoptionalsswiftui

if let enters its branch only when the optional contains a value.

  • nil makes the condition fail without a crash.
  • The bound name is non-optional inside the branch.
  • else handles the missing-value path explicitly.

Why interviewers ask this: This checks the candidate's junior-level understanding of optional binding.

control-flowoptional-binding

guard let suits a precondition whose failure should exit early.

  • Its else block must return, throw, break, or continue.
  • The unwrapped value remains available after guard.
  • It keeps the successful path from becoming deeply nested.

Why interviewers ask this: This checks the candidate's junior-level understanding of optional control flow.

indexes

String uses String.Index because one Character may contain several Unicode scalars.

  • startIndex identifies the first valid character boundary.
  • index(after:) advances to another valid boundary.
  • Array(string) is simpler for tiny tasks but allocates storage.

Why interviewers ask this: This checks the candidate's junior-level understanding of Unicode-safe strings.

Array is ordered, Set is unique, and Dictionary maps keys to values.

  • Array allows duplicates and position-based access.
  • Set suits fast membership checks when order is irrelevant.
  • Dictionary lookup returns an optional because a key may be absent.

Why interviewers ask this: This checks the candidate's junior-level understanding of collection choice.

A tuple groups a fixed set of related values without a new named type.

  • Named fields make (code: 200, message: "OK") readable.
  • A function can return two small results in one tuple.
  • Use a struct when data needs methods or broad reuse.

Why interviewers ask this: This checks the candidate's junior-level understanding of tuples.

a...b includes b, while a..<b excludes b.

  • 1...3 produces 1, 2, and 3.
  • 0..<array.count matches ordinary integer positions.
  • Iterate elements directly when no index is needed.

Why interviewers ask this: This checks the candidate's junior-level understanding of range boundaries.

A function can return a named tuple for a small one-off result.

  • A return type may be (min: Int, max: Int).
  • Callers read result.min and result.max.
  • Use a struct when the result becomes a domain model.

Why interviewers ask this: This checks the candidate's junior-level understanding of function return values.

Argument labels describe parameters at the call site.

  • move(from: 1, to: 3) reads like a sentence.
  • The internal parameter name can differ from its label.
  • Use _ only when omitting a label stays clear.

Why interviewers ask this: This checks the candidate's junior-level understanding of argument labels.

A default lets callers omit an optional argument while sharing one implementation.

  • greet(name:punctuation:) can default punctuation to "!".
  • An explicit argument overrides the default.
  • Required business input should not be hidden behind a default.

Why interviewers ask this: This checks the candidate's junior-level understanding of default parameters.

inout lets a function modify a variable supplied by its caller.

  • The declaration places inout before the parameter type.
  • The call uses &, as in increment(&count).
  • A let constant cannot be passed because mutation is required.

Why interviewers ask this: This checks the candidate's junior-level understanding of inout mutation.

closures

A closure is executable code that can be stored and passed as a value.

  • It may capture names from its surrounding scope.
  • map and filter accept closures.
  • Trailing syntax moves a final closure outside parentheses.

Why interviewers ask this: This checks the candidate's junior-level understanding of closure basics.

escaping-closures

@escaping means a parameter closure may outlive the function call.

  • Stored completion handlers commonly need @escaping.
  • A nonescaping closure finishes during the call.
  • An escaping closure uses explicit self when capturing an instance.

Why interviewers ask this: This checks the candidate's junior-level understanding of escaping closures.

enums

Raw values give every case one fixed value of a shared primitive type.

  • A Direction: String enum can expose string raw values.
  • init(rawValue:) is failable because input may not match.
  • The raw value is declared once, not supplied per instance.

Why interviewers ask this: This checks the candidate's junior-level understanding of enum raw values.

Associated values attach runtime data to a particular enum case.

  • Cases may carry different types, such as success(Data).
  • A switch pattern extracts the attached value.
  • Raw values are fixed, while associated values vary per instance.

Why interviewers ask this: This checks the candidate's junior-level understanding of associated values.

Locked questions

  • 21

    When would you choose a struct over a class?

    swiftvalue-typesreference-types
  • 22

    How do stored and computed properties differ?

  • 23

    What are willSet and didSet?

  • 24

    Why must a struct method sometimes be mutating?

    swiftvalue-typesmutation
  • 25

    What is an initializer responsible for?

  • 26

    What does a protocol define?

    typingprotocols
  • 27

    What can an extension add?

    extensions
  • 28

    Why use a generic function instead of Any?

    generics
  • 29

    How do throws, try, and do-catch work together?

    error-handling
  • 30

    When is Result useful?

    result-type
  • 31

    What does defer do?

    resource-cleanup
  • 32

    What does ARC manage?

    memory
  • 33

    How do weak and unowned differ?

    memorymemory-management
  • 34

    What does Codable provide?

    codableserialization
  • 35

    How do CodingKeys help with JSON?

    serialization
  • 36

    What do URL, Data, and Date represent in Foundation?

  • 37

    How do private, fileprivate, internal, and public differ?

  • 38

    What is a Swift module and what does import do?

    swiftmodules
  • 39

    What are package, target, and product in SPM?

    swift-package-manager
  • 40

    What do async and await mean?

    asyncconcurrency
  • 41

    What is Task used for?

    structured-concurrency
  • 42

    What does @MainActor guarantee?

    actor-isolation
  • 43

    What problem does an actor solve?

    concurrency
  • 44

    What does Sendable express?

    concurrency
  • 45

    What is the basic structure of an XCTest test?

    xctestswiftvalue-types
  • 46

    What are setUp and tearDown for?

  • 47

    What is the boundary between a SwiftUI View and state?

    swiftuiswift
  • 48

    How do SwiftUI and UIKit differ?

    uikitswiftuiswift
  • 49

    How can a Swift CLI read process arguments?

    concurrencyswift
  • 50

    What does a simple Vapor route do?

    server-side
  • 51

    Int("abc") returns nil. How should a CLI report invalid input?

  • 52

    A force unwrap crashes when a JSON field is absent. What should change?

  • 53

    A missing nickname must display "Guest". Which optional expression fits?

    swiftoptionals
  • 54

    Decoding reports keyNotFound for a sometimes absent field. How do you fix the model?

  • 55

    JSON has "age": "20", but the model uses Int. Why does decoding fail?

  • 56

    JSON uses user_id while Swift uses userID. What fixes keyNotFound locally?

    swift
  • 57

    Removing Array elements while traversing old indices crashes. How do you rewrite it?

  • 58

    counts[word] += 1 does not compile for a Dictionary. Why?

  • 59

    After var b = a, appending to Array b leaves a unchanged. Is that expected?

  • 60

    Changing b.name also changes a.name after let b = a for a class. Why?

    reference-types
  • 61

    text[0] gives a compiler error. How do you read the first Character?

  • 62

    A stored closure prints the latest counter, not its creation-time value. How do you capture a snapshot?

    closuressnapshot
  • 63

    An @escaping callback requires explicit self for a property. What does the compiler want?

    callbacksescaping-closures
  • 64

    A controller never deinitializes after storing a closure that uses self. What is likely wrong?

    closures
  • 65

    A [weak self] callback finds self nil when it runs. Is that necessarily a bug?

    callbacksmemory
  • 66

    A type misses a protocol get-set property requirement. What must it provide?

    typingprotocols
  • 67

    Protocol Resettable requires mutating func reset(), but a struct's reset gets 'self is immutable' at count = 0. What fixes it?

    immutabilitytypingswift
  • 68

    A generic maximum cannot use > on unconstrained T. What is missing?

    generics
  • 69

    readFile() says the throwing call is not marked with try. What are the choices?

  • 70

    A general catch hides a known invalidInput case. How do you preserve its message?

  • 71

    A function prints an error, then its caller continues as if work succeeded. What should change?

  • 72

    A file handle stays open when parsing throws. What guarantees cleanup?

    error-handling
  • 73

    An async call says it is not marked with await. What is required?

    asyncconcurrency
  • 74

    A synchronous button callback must call async load(). What is the small boundary fix?

    asynccallbacksconcurrency
  • 75

    Cancelling a Task does not stop its long loop. What is missing?

    structured-concurrency
  • 76

    Two tasks increment a counter, but the final value is too small. How can an actor help?

    concurrency
  • 77

    Reading counter.value outside an actor gives an isolation error. What should the caller do?

    concurrency
  • 78

    Async work updates UI state and triggers an actor warning. How do you fix it?

    asyncconcurrencystate
  • 79

    Capturing a mutable class in a @Sendable closure warns. What is a beginner-safe redesign?

    closuresconcurrencyreference-types
  • 80

    Two independent async fetches run sequentially. How can both start before awaiting?

    asyncconcurrency
  • 81

    An XCTest needs a value from async loadName(). What signature works?

    asyncconcurrencytesting
  • 82

    parse("bad") must throw. How should XCTest verify it?

    xctest
  • 83

    A test passes alone but fails after another test mutates a singleton. What is the first repair?

  • 84

    SPM says no such module Utility although the target exists. What should you inspect first?

    swift-package-managermodules
  • 85

    A product is ToolsKit, but its module is ToolsCore. Which name belongs in import?

    modules
  • 86

    SPM expects AppCLI sources under Sources/AppCLI. What are two valid fixes?

    swift-package-manager
  • 87

    FileManager cannot find config.json from a CLI. How do you debug the path?

    configfile-system
  • 88

    A JSON CLI prints only "decode failed". How do you expose the useful cause?

  • 89

    A CLI crashes on CommandLine.arguments[1] with no arguments. What is the minimal fix?

  • 90

    ArgumentParser requires --input, but the user omits it. What should happen?

    argument-parser
  • 91

    ArgumentParser receives --count many for Int. Where should failure happen?

    argument-parser
  • 92

    GET /users returns 404, but Vapor registered app.post. What is wrong?

    server-side
  • 93

    The Vapor route /users/:id matches /users/abc, but the handler needs an Int id. Which response and fix are correct?

    server-side
  • 94

    A Vapor POST receives malformed JSON for Content. What should the handler do?

    server-side
  • 95

    A Vapor request accepts an empty username and fails later. Where should validation occur?

    validationserver-side
  • 96

    A Vapor lookup returns nil for user 42. Which status beats an empty 200?

    server-side
  • 97

    A Vapor async handler calls a throwing service without try await. What is needed?

    asyncconcurrencyserver-side
  • 98

    A SwiftUI button changes a local var in body, but text never updates. What is needed?

    swiftuiswift
  • 99

    A SwiftUI List loses rows because items share an id. What must change?

    swiftuiswift
  • 100

    A reused UITableViewCell briefly shows the previous row's asynchronously loaded image. How do you fix it?

    asyncconcurrencyuikit