iOS Developer interview questions
100 real questions with model answers and explanations for Junior candidates.
See a iOS Developer resume example →Practice with flashcards
Spaced repetition · Hunter Pass
Questions
let declares a constant that cannot be reassigned, while var declares a value that may change.
- Prefer let by default because it makes intended immutability explicit.
- A let reference to a class instance cannot point to another instance, but the object's mutable properties may still change.
- For a struct stored in let, its variable properties cannot be changed because the whole value is constant.
Why interviewers ask this: The interviewer checks whether the candidate understands assignment rules and the effect of value versus reference semantics.
Swift usually infers a variable's type from its initial value, while an annotation states the intended type directly.
- let count = 3 is inferred as Int, and let price: Double = 3 requests a Double.
- An annotation is useful when the desired protocol, numeric type, or optionality is not obvious from the initializer.
- Swift remains statically typed, so an inferred variable cannot later hold an unrelated type.
Why interviewers ask this: A strong answer distinguishes concise inference from dynamic typing and knows why annotations clarify intent.
An Optional represents either a wrapped value of a specific type or the absence of that value as nil.
- String? is shorthand for Optional<String> and cannot be used as a plain String without handling nil.
- Optionals make missing data part of the type system instead of relying on magic values.
- Common sources include failed lookups, missing input, and APIs where a result may not exist.
Why interviewers ask this: The interviewer evaluates whether nil is understood as an explicit type state rather than a normal value of every type.
Optionals should be unwrapped with optional binding, guard, optional chaining, or a justified default value.
- if let handles a value within one branch, while guard let exits early and keeps the unwrapped value available afterward.
- The nil-coalescing operator supplies a fallback, and optional chaining continues only when the value exists.
- Force unwrapping with ! is appropriate only when an invariant truly guarantees a value, because nil causes a runtime crash.
Why interviewers ask this: A strong answer presents several safe tools and treats force unwrapping as an exceptional invariant.
guard is useful for validating required conditions early and leaving the main success path less nested.
- A guard branch must transfer control with return, throw, break, or continue when its condition fails.
- Values bound by guard let remain available in the rest of the current scope.
- It fits required preconditions, while if is clearer when both branches represent normal alternatives.
Why interviewers ask this: The interviewer checks whether the candidate can choose control flow based on early-exit semantics rather than style alone.
Optional chaining safely follows properties or methods through an optional, and nil coalescing supplies a fallback if the result is nil.
- user.profile?.displayName returns an optional because any optional link may be absent.
- Appending ?? "Guest" converts that missing result into a non-optional display value.
- Chaining avoids deeply nested binding when the operation only needs to continue on existing values.
Why interviewers ask this: The interviewer evaluates whether the candidate can express safe access and a deliberate fallback without force unwrapping.
A struct is a value type, while a class is a reference type with identity, inheritance, and deinitialization.
- Assigning or passing a struct creates an independently behaving value through copy semantics.
- Assigning a class instance copies the reference, so multiple variables can observe mutations to the same object.
- Prefer structs for simple data models and classes when shared identity or class-only behavior is required.
Why interviewers ask this: A strong answer connects language features to ownership and modeling choices instead of listing syntax only.
Value semantics give each variable its own logical value, while reference semantics let variables share one object instance.
- Swift structs, enums, arrays, and dictionaries use value semantics.
- Class instances use reference semantics, so changing an object through one reference is visible through the others.
- Value semantics reduce accidental shared mutation, while reference semantics are useful when object identity matters.
Why interviewers ask this: The interviewer checks whether the candidate can predict the effect of assignment and mutation for common Swift types.
A struct method needs mutating when it changes a stored property or replaces self.
- Value-type instance methods are nonmutating by default.
- Marking the method states that calling it may produce a changed value.
- The method still cannot mutate an instance stored in a let constant.
Why interviewers ask this: The interviewer evaluates whether the candidate understands mutation rules for value types.
A raw value is a predefined constant attached to each case, while associated values carry data for one particular enum instance.
- Raw values share one type such as String or Int and can support initialization from that value.
- Associated values may have different types and labels for different cases.
- A switch extracts associated data with pattern matching, making enums suitable for state with case-specific payloads.
Why interviewers ask this: A strong answer distinguishes fixed case metadata from runtime payloads.
Swift requires every possible enum case to be handled so the switch always produces defined control flow.
- Listing all known cases lets the compiler report a missing branch when the local enum changes.
- default handles all remaining cases but can hide newly added cases in app-owned enums.
- @unknown default is useful for non-frozen system enums that Apple may extend in future SDKs.
Why interviewers ask this: The interviewer checks whether exhaustive matching is connected to compiler safety and API evolution.
Argument labels shape the call site, parameter names are used inside the function, and default values make selected arguments optional to provide.
- A declaration such as move(from start: Int, to end: Int) uses from and to at the call site and start and end in the body.
- An underscore removes an external argument label when that produces a natural call.
- Defaults should represent a sensible common behavior rather than hide important choices.
Why interviewers ask this: The interviewer evaluates whether the candidate can read and design idiomatic Swift function signatures.
A protocol defines a contract of properties, methods, initializers, or other capabilities that conforming types must provide.
- Structs, classes, and enums can all conform to protocols.
- Code can accept a protocol instead of one concrete type, reducing coupling to an implementation.
- Protocols describe required behavior but do not normally store instance data themselves.
Why interviewers ask this: A strong answer explains protocols as contracts that enable substitution across different Swift types.
A protocol extension can provide shared default implementations and helper behavior for conforming types.
- A conforming type inherits the default when it does not supply its own implementation.
- Requirements declared in the protocol can be dynamically satisfied by the concrete implementation.
- Extension-only methods follow static dispatch when called through a protocol-typed value, which differs from protocol requirements.
Why interviewers ask this: The interviewer checks basic protocol-oriented reuse and awareness that extension-only methods have different dispatch behavior.
An extension adds methods, computed properties, protocol conformance, and other supported behavior to an existing type.
- It helps organize a type by responsibility without creating a subclass.
- Extensions can add computed properties but cannot add stored instance properties.
- A type from another module can gain local conveniences or protocol conformance when access rules allow it.
Why interviewers ask this: The interviewer evaluates whether the candidate knows both the organizational value and storage limitation of extensions.
Generics let one type-safe implementation work with multiple types while preserving their relationships.
- A generic function can accept T without converting values to Any and casting them back.
- Constraints such as T: Equatable permit operations guaranteed by the required protocol.
- Collections like Array<Element> and Dictionary<Key, Value> are standard generic types.
Why interviewers ask this: A strong answer connects reusable code with compile-time type safety and protocol constraints.
Equatable defines value equality, while Hashable also supplies a hash for use in sets and dictionary keys.
- Equal values must always produce the same hash within one execution.
- Hashable inherits from Equatable, so a hashable type supports both operations.
- Swift can synthesize conformances when all relevant stored properties conform and their generated meaning is correct.
Why interviewers ask this: The interviewer checks whether equality and hashing are understood as collection contracts rather than unrelated protocols.
Choose Array for ordered elements, Set for unique membership, and Dictionary for values addressed by unique keys.
- Array preserves position and allows duplicates.
- Set provides efficient membership checks when order and duplicates are not part of the model.
- Dictionary maps each Hashable key to one value and returns an optional when a key is absent.
Why interviewers ask this: The interviewer evaluates whether the collection matches ordering, uniqueness, and lookup requirements.
They transform a collection in distinct ways without requiring manual result-building loops.
- map converts every element, while filter keeps elements that satisfy a condition.
- compactMap converts elements and removes nil results.
- reduce combines the sequence into one accumulated result such as a sum or grouped value.
Why interviewers ask this: A strong answer distinguishes the output shape and purpose of each common collection operation.
A closure is a self-contained block of executable code that can be stored, passed, and called later.
- It can accept parameters and return a value like a function.
- It captures constants and variables from the surrounding scope so they remain available when called.
- Swift supports shorthand arguments and trailing-closure syntax, but clear names are better for nontrivial logic.
Why interviewers ask this: The interviewer checks whether the candidate understands closures as callable values with captured context.
Locked questions
- 21
What is the difference between escaping and nonescaping closures?
closures - 22
What does a capture list do in a Swift closure?
closuresswift - 23
How does Swift error handling with throws, try, do, and catch work?
error-handlingswift - 24
What does Swift's Result type represent?
swift - 25
How do Swift access levels differ?
swift - 26
How do initialization rules differ between structs and classes?
swift - 27
What is Automatic Reference Counting in Swift?
swift - 28
How can two class instances create a strong reference cycle?
memory - 29
When should a reference be weak, and when should it be unowned?
memory - 30
How can an escaping closure create a retain cycle with self?
closuresmemory - 31
How do UIKit and SwiftUI differ?
uikitswiftuiswift - 32
What does the body property of a SwiftUI View represent?
swiftuiswift - 33
What are the key UIViewController lifecycle callbacks when a screen appears?
callbacks - 34
How do loadView and viewDidLoad differ?
lifecycle - 35
How do viewWillAppear and viewDidAppear differ from viewDidLoad?
lifecycle - 36
What roles do AppDelegate and SceneDelegate have in a UIKit app?
uikit - 37
What is Auto Layout and how does it determine view frames?
layout - 38
What is the difference between an ambiguous and an unsatisfiable Auto Layout configuration?
layoutconfig - 39
What are intrinsic content size, content hugging, and compression resistance?
autolayout - 40
Why is translatesAutoresizingMaskIntoConstraints usually set to false for programmatic Auto Layout?
layout - 41
What responsibilities are required to display data in a UITableView?
uikit - 42
Why do UITableView and UICollectionView reuse cells?
uikit - 43
How do UITableViewDataSource and UITableViewDelegate differ?
uikit - 44
When would UICollectionView be preferable to UITableView?
uikit - 45
What does a UICollectionView layout object control?
uikit - 46
How does the delegate pattern work in iOS?
delegationprotocols - 47
How does UINavigationController manage navigation?
navigation - 48
How does modal presentation differ from navigation-controller push?
navigation - 49
What are the trade-offs between Storyboards and building UIKit screens in code?
uikit - 50
What are IBOutlet and IBAction used for in a Storyboard-based UIKit screen?
uikit - 51
How would you build a UIKit screen that loads and displays products from an API?
uikitapi - 52
A list screen can be loading, empty, failed, or populated; how would you implement those states?
- 53
How would you implement UITableView cell reuse without showing stale content?
uikitviews - 54
How would you update a table after inserting and deleting items without getting invalid update errors?
- 55
A self-sizing table cell is clipped or has the wrong height; how would you fix it?
- 56
How would you add pagination to a UITableView backed by a REST API?
restpaginationuikit - 57
How would you build a two-column photo grid with UICollectionView?
griduikitschema - 58
Selected collection-view cells display the wrong state after scrolling; how would you fix it?
- 59
How would you load remote images in reusable cells without wrong images flashing?
- 60
How would you add pull-to-refresh to a list that already supports pagination?
pagination - 61
How would you implement and decode a GET request with URLSession?
networking - 62
How would you send a JSON POST request and handle its response?
- 63
A URLSession request finishes but the UI sometimes updates incorrectly; how would you fix the threading?
networkingconcurrency - 64
How would you cancel an obsolete network request when a search query changes?
queries - 65
How would you handle offline and transient failures on an API-backed screen?
api - 66
How would you test a URLSession-based API client without calling the real server?
networkingapi - 67
How would you attach an authentication token to requests without storing it insecurely?
authtokens - 68
An endpoint returns valid JSON but Decodable fails; how would you debug it?
endpoints - 69
A view has ambiguous Auto Layout and moves unpredictably; how would you debug it?
layout - 70
Xcode logs 'Unable to simultaneously satisfy constraints'; how would you find the conflict?
autolayoutxcode - 71
A label truncates while a neighboring button expands; how would you adjust Auto Layout priorities?
layout - 72
A form is hidden by the keyboard; how would you fix the layout?
forms - 73
A reusable table cell starts producing constraint warnings only after scrolling; how would you investigate?
autolayout - 74
How would you make a UIKit screen adapt to rotation and Dynamic Type?
uikit - 75
How would you choose between pushing a screen and presenting it modally?
- 76
How would you pass a selected item from a list to a detail screen?
- 77
How would a modal edit screen return a saved value to the presenting screen?
- 78
How would you route a deep link to a nested detail screen?
- 79
How would you combine a tab bar with independent navigation flows?
navigationcombine - 80
How would you implement value-driven navigation in SwiftUI?
swiftuinavigationswift - 81
A view controller never deinitializes after dismissal; how would you find a retain cycle?
uikitmemory - 82
How would you fix a retain cycle caused by an escaping closure?
closuresmemory - 83
A photo screen receives memory warnings and is terminated; what would you change first?
memory - 84
An app crashes with 'index out of range'; how would you diagnose and fix it?
indexes - 85
How would you use an iOS crash report to locate the failing code?
- 86
A completion handler updates a label after its screen was dismissed; how would you fix it?
- 87
How would you implement a simple favorites screen with Core Data?
core-data - 88
A Core Data import freezes scrolling; how would you move it off the main thread safely?
core-dataconcurrency - 89
A Combine-powered search fires duplicate requests and keeps subscriptions alive; how would you fix it?
combine - 90
How would you structure a small MVVM feature that loads a user profile?
architecture-patternsswift - 91
How would you implement validation for a sign-up form?
formsvalidation - 92
How would you add photo-library selection and handle denied permission?
- 93
How would you make a custom product cell accessible?
- 94
How would you unit-test a view model that loads data asynchronously?
asyncconcurrencyhypothesis-testing - 95
How would you write a reliable UI test for adding an item to favorites?
- 96
How would you preserve an unfinished draft when the app moves to the background?
- 97
How would you add a third-party package with Swift Package Manager safely?
npmdependenciesdependency-management - 98
How would you call an existing Objective-C utility from new Swift code?
swift - 99
A table stutters while scrolling; how would you find and remove the bottleneck?
tracking - 100
How would you implement an offline-capable favorite button on a product detail screen?