iOS quiz questions
Short, clear answers to the questions interviewers ask most.
Swift, memory, concurrency, UIKit, SwiftUI, architecture and more. Each answer starts with a TL;DR, then shows code examples and follow-up questions.
Short answers to the iOS questions interviewers ask most.
Structs are value types and get copied. Classes are reference types and are shared.
Easy3 minsSwiftValue semantics means each copy is independent; copy-on-write makes copies cheap by sharing storage until someone mutates it.
Medium3 minsSwiftPerformanceAn optional either holds a value or nil; unwrap it with if let, guard let, ?? or optional chaining instead of force unwrapping.
Easy2 minsSwiftProtocol-oriented programming means building behavior from small protocols with default implementations, instead of deep class inheritance.
Medium2 minsSwiftProtocolsSwift uses static dispatch when it knows the exact method, table dispatch for class overrides and protocol requirements, and message dispatch for @objc dynamic.
Hard3 minsSwiftPerformanceAn associated type is a placeholder type inside a protocol that each conforming type fills in with a real type.
Medium2 minsSwiftProtocolsGenericssome is an opaque type that stands for one specific concrete type the compiler knows; any is a box that can hold any conforming type at run time.
Medium3 minsSwiftProtocolsGenericsAssociated values let each enum case carry its own extra data, which is great for modeling states where only valid combinations are possible.
Easy2 minsSwift- What is an escaping closure in Swift?Asked often
An escaping closure can be called after the function that received it returns, so it must be marked @escaping and you must think about what it captures.
Easy2 minsSwiftMemory & ARC - What is a capture list in a Swift closure?Asked often
A capture list, like [weak self] or [count], controls how a closure captures values, either by making references weak or by copying a value at creation time.
Medium3 minsSwiftMemory & ARC A property wrapper is a type that wraps the get and set logic of a property so you can reuse it with an @Attribute, like @State or @Published.
Medium2 minsSwiftSwiftUIA result builder is a type marked @resultBuilder that turns a list of statements in a closure into one combined value, which is how SwiftUI's @ViewBuilder works.
Hard2 minsSwiftSwiftUI- How does error handling work in Swift?Asked often
Functions mark failure with throws, callers handle it with do/catch, try? or try!, and Swift 6 adds typed throws for a fixed error type.
Easy2 minsSwift Swift has six levels, open, public, package, internal, fileprivate and private, that control who can see and use a declaration.
Easy2 minsSwiftmutating lets a method on a struct or enum change self, and inout lets a function change a variable that the caller passes in with &.
Easy2 minsSwiftEquatable gives ==, Hashable lets a type be a Set element or Dictionary key, and Comparable gives <; Swift writes them for you when all stored properties already conform.
Easy2 minsSwiftProtocolsA key path like \User.name is a type-safe reference to a property that you can store, pass around and use later to read or write that property.
Medium2 minsSwiftA lazy property computes its value the first time it is read, which saves work for expensive values that may never be used.
Easy3 minsSwiftBoth create type-level members, but class members can be overridden by subclasses while static members cannot.
Easy2 minsSwiftGenerics let you write one function or type that works with many types, and constraints limit those types to ones that have the abilities you need.
Medium2 minsSwiftGenericsProtocolsSwift macros generate code at compile time from your source, using either a freestanding
Hard3 minsSwiftToolingThe Swift 6 language mode turns data-race checks into compile errors, so shared mutable state must be isolated to an actor or be Sendable; you migrate module by module, starting with warnings.
Hard3 minsSwiftConcurrency- How does ARC work in Swift?Asked often
ARC counts strong references to each class instance and frees the instance as soon as the count reaches zero, with retain and release calls inserted by the compiler.
Medium3 minsMemory & ARCSwift A strong reference keeps an object alive, a weak reference does not and becomes nil when the object dies, and an unowned reference does not and crashes if used after the object dies.
Easy3 minsMemory & ARCA retain cycle happens when objects hold strong references to each other so their counts never reach zero; you break it by making one link weak or unowned.
Medium2 minsMemory & ARCCheck that deinit runs, use Xcode's Memory Graph Debugger to see who holds an object, use the Leaks and Allocations instruments, and add tests that assert objects are freed.
Medium3 minsMemory & ARCToolingPerformanceThe stack is fast, per-thread memory freed automatically when a function returns, while the heap is shared memory for data that must outlive a function, like class instances, managed by ARC.
Medium3 minsMemory & ARCPerformanceGCD is a lightweight C-based API for running closures on queues, while OperationQueue is a higher-level Objective-C API built on GCD that adds dependencies, cancellation and concurrency limits.
Medium2 minsConcurrency- How does async/await work in Swift?Asked often
An async function can pause at each await without blocking its thread, letting Swift run other work on that thread until the result is ready.
Medium2 minsConcurrency An actor is a reference type that protects its mutable state by running only one task at a time on it, and reentrancy means its state can change while one of its methods is suspended at an await.
Medium2 minsConcurrency@MainActor is a global actor that runs code on the main thread, and marking UI types and methods with it lets the compiler check that UI updates happen there.
Medium2 minsConcurrencySendable marks types whose values can safely cross between concurrency domains, like tasks and actors, without causing data races.
Hard3 minsConcurrencyA task group runs a dynamic number of child tasks in parallel and collects their results, while async let is for a fixed, small number of tasks known at compile time.
Medium3 minsConcurrencyCancellation in Swift is cooperative; cancel() only sets a flag, and your code must check Task.isCancelled or call try Task.checkCancellation() to stop.
Medium2 minsConcurrencyA serial queue runs one task at a time in order while a concurrent queue can run many at once, and sync waits for the work to finish while async returns immediately.
Easy2 minsConcurrencyA deadlock is when threads wait for each other forever, a data race is unsynchronized access to the same memory with at least one write, and a race condition is a logic bug that depends on timing.
Medium3 minsConcurrencyProtect shared mutable state with an actor, a lock or Mutex, a serial queue, or atomics, or avoid sharing it by using immutable value types and main-actor isolation.
Medium3 minsConcurrencyAsyncStream turns callback, delegate or notification APIs that produce many values over time into an AsyncSequence you can loop over with for await.
Medium2 minsConcurrencyA continuation suspends an async function until a callback calls resume exactly once, which lets you wrap completion-handler APIs as async functions.
Medium2 minsConcurrency- Explain the UIViewController lifecycle.Asked often
A view controller creates its view, loads it once in viewDidLoad, then gets appear and disappear callbacks every time it shows or hides.
Easy2 minsUIKitApp lifecycle The frame is the view's rectangle in its superview's coordinates, while bounds is the same view described in its own coordinates.
Easy2 minsUIKitAuto Layout solves a set of constraint equations to find each view's frame, and hugging and compression resistance priorities decide which view grows or shrinks first.
Medium2 minsUIKitA table view keeps a small pool of cells and reuses them for new rows, so you must fully reset each cell or you will see old data.
Easy2 minsUIKitPerformanceA diffable data source takes snapshots of section and item identifiers and computes the inserts, deletes and moves for you, so the UI never gets out of sync with the data.
Medium2 minsUIKitHit-testing finds the deepest view under a touch, and the responder chain passes unhandled events and actions up from that view to its superviews, view controller, window and app.
Medium2 minsUIKit- Explain the layout cycle. What is the difference between setNeedsLayout and layoutIfNeeded?Asked often
UIKit updates constraints, then lays out views, then draws them once per run loop pass, and setNeedsLayout schedules layout for later while layoutIfNeeded runs it right now.
Medium2 minsUIKitPerformance Delegation lets one object hand some decisions or events to another object through a protocol, and the delegate property is weak to avoid a retain cycle.
Easy2 minsUIKitProtocolsMemory & ARCThe @State wrapper owns data inside a view, @Binding gives a child read-write access to someone else's data, @Bindable makes bindings to an @Observable object, and @Environment reads shared values from above.
Medium2 minsSwiftUIThe @Observable macro makes a class track reads and writes of each property, so SwiftUI only updates views that read the changed property, while ObservableObject updates every observer on any change.
Medium2 minsSwiftUICombineSwiftUI uses identity to decide if a view is the same one as before, and identity controls how long state lives and whether changes animate or reset.
Hard2 minsSwiftUIPerformanceWrap UIKit views with UIViewRepresentable or UIViewControllerRepresentable, and host SwiftUI inside UIKit with UIHostingController or UIHostingConfiguration.
Medium2 minsSwiftUIUIKitNavigationStack drives navigation from data, so you push by appending values to a path and map each value type to a screen with navigationDestination.
Medium2 minsSwiftUIArchitectureKeep body cheap, make each view depend on as little data as possible, keep identities stable, use lazy containers, and measure with the SwiftUI instrument.
Hard2 minsSwiftUIPerformanceA SwiftUI view struct is created and thrown away often, but its state lives as long as its identity, and onAppear, onDisappear and task tie work to when it is shown.
Medium2 minsSwiftUIConcurrencyMVC is simple but leads to huge view controllers, MVVM moves logic into a testable view model, VIPER splits a screen into many small roles, and TCA uses one state, actions and a reducer.
Medium3 minsArchitectureA coordinator owns navigation, so view controllers do not know about each other and screens become reusable and easy to test.
Medium2 minsArchitectureUIKitDependency injection means an object gets its dependencies from outside instead of creating them, which makes code easy to test and change.
Medium2 minsArchitectureTestingSplit the app into local Swift packages with clear layers, like core, features and interfaces, so builds are faster, boundaries are enforced and teams can work in parallel.
Hard2 minsArchitectureToolingA singleton gives one shared instance through a global access point, which is convenient but hides dependencies, shares mutable state and makes testing hard.
Easy2 minsArchitectureSwiftConcurrencyBuild a URLRequest, call try await session.data(for:), check the HTTP status code, then decode the data, and choose a session configuration for caching, timeouts or background transfers.
Easy2 minsNetworkingConcurrencyCodable lets the compiler generate encoding and decoding code, and you customize it with CodingKeys, decoder strategies or a hand-written init(from:).
Easy1 minsNetworkingSwiftLet URLCache handle HTTP caching with Cache-Control and ETag headers, and add your own memory and disk cache for decoded, downsampled images.
Medium2 minsNetworkingPerformanceREST uses many resource URLs and is simple to cache, GraphQL uses one endpoint where the client picks the fields it needs, and WebSockets keep a two-way connection open for real-time data.
Medium2 minsNetworkingSystem designUse UserDefaults for small settings, the Keychain for secrets, files for documents and caches, and SwiftData, Core Data or SQLite for structured data you query.
Easy3 minsPersistenceSecurityEach managed object context belongs to one queue, so you work inside perform, use the view context only on the main thread, and pass NSManagedObjectID values between contexts instead of objects.
Hard2 minsPersistenceConcurrencySwiftData is Apple's Swift-first persistence framework where you mark classes with @Model, read them with @Query and save through a ModelContext, built on Core Data's proven storage.
Medium2 minsPersistenceSwiftUIAn app moves between not running, inactive, active, background and suspended states, with AppDelegate handling process-level events and SceneDelegate handling each window's UI lifecycle.
Easy2 minsApp lifecycleUIKitSwiftUIiOS suspends apps quickly, so you use beginBackgroundTask for short finishing work, BGTaskScheduler for deferred tasks, background URLSession for transfers, and special background modes for audio, location or VoIP.
Medium2 minsApp lifecyclePerformanceThe app asks for permission, registers with APNs to get a device token, sends the token to its server, and the server sends a JSON payload to APNs, which delivers it to the device.
Medium2 minsApp lifecycleNetworkingUniversal links are normal https links that open your app when a verified apple-app-site-association file on your domain lists it, while custom URL schemes are unverified and any app can claim them.
Medium2 minsApp lifecycleSecuritySwift Testing uses @Test functions with expect and require macros, parameterized tests and parallel runs by default, while XCTest uses XCTestCase subclasses and XCTAssert functions, and both can live in the same target.
Easy2 minsTestingHide each dependency behind a protocol or closure, inject it, and in tests pass a test double such as a stub that returns fixed data or a spy that records calls.
Medium2 minsTestingArchitectureXCUITest drives the app from a separate process through accessibility, so you find elements by accessibility identifiers, wait for them instead of sleeping, and control app state with launch arguments.
Medium2 minsTestingAccessibilityMeasure cold launch with Instruments, XCTest metrics and the Xcode Organizer, then cut pre-main work like dynamic frameworks and static initializers and defer everything not needed for the first frame.
Hard3 minsPerformanceApp lifecycleStutters are hitches where a frame misses its deadline, usually from main thread work in cell setup, image decoding, layout or offscreen rendering, so you measure with Instruments and move or remove that work.
Medium2 minsPerformanceUIKitUse Time Profiler for slow code, Allocations and Leaks for memory, Animation Hitches for stutters, the SwiftUI and Swift Concurrency instruments for those frameworks, and signposts to mark your own code.
Medium3 minsPerformanceToolingMemory & ARCDo less work and do it at better times, by batching network calls, using low location accuracy, avoiding timers and polling, letting the system schedule background work, and measuring with the energy tools.
Medium2 minsPerformance- How do you store sensitive data securely on iOS? Explain the Keychain and Data Protection.Asked often
Store small secrets like tokens in the Keychain with the right accessibility class, protect files with Data Protection, and use the Secure Enclave and biometrics for the most sensitive keys.
Medium2 minsSecurityPersistence ATS forces secure HTTPS connections by default, and pinning goes further by only trusting specific server keys, which you set with NSPinnedDomains in Info.plist or check yourself in a URLSession delegate.
Hard2 minsSecurityNetworkingA certificate proves who signed the app, the provisioning profile says which app, devices and entitlements that certificate may use, and iOS refuses to run code whose signature or profile does not match.
Medium3 minsToolingSecurityA target is what you build, a build configuration is a set of build settings like Debug or Release, and a scheme says which targets and configurations to use when you run, test, profile or archive.
Easy3 minsToolingRun build, lint and tests on every pull request on a macOS runner, and on main or a tag archive a signed build, bump the build number and upload it to TestFlight automatically.
Medium2 minsToolingTestingCombine is Apple's reactive framework where publishers emit values over time, operators transform them, and subscribers receive them, with AnyCancellable controlling how long a subscription lives.
Medium2 minsCombineConcurrency- How do you make an iOS app accessible?Asked often
Give every element a clear label, value and trait for VoiceOver, support Dynamic Type, keep good contrast and large tap targets, respect Reduce Motion, and test with VoiceOver and Accessibility Inspector.
Easy2 minsAccessibilitySwiftUIUIKit