← All topics/Performance & optimization

Practical interview questions

Scenario-style prompts with sample answer outlines. Focus is on how you would design and reason in real codebases.

Question 1

Diagnosing scrolling jank

You’re building a feed with complex cells, images, gradients, async content, dynamic text, and scrolling feels janky. Walk me through how you would diagnose and fix it.

Follow-ups

  • What tools would you use?
  • How do you tell layout, rendering, image decoding, and main-thread work apart?

Answer outline

Reproduce first: same device class, Release schema, real data volume. Note whether jank is constant (every frame) or spikes when new rows appear or images.

Profile before guessing: Hook up a real device to Instruments → Time Profiler (main thread + heaviest symbols). Look for main-thread stacks doing decode, JSON, regex, or layout thrash.

Separate the four causes:

  1. 1.Layout (long _UIViewLayoutEngine stacks, constraint thrash) — simplify constraints, split heavy cells, cache row heights, eliminate layoutIfNeeded() storms.
  2. 2.Rendering (offscreen layers, blur, shadows) — reduce layer effects or rasterize deliberately.
  3. 3.Images (large assets hitting the main thread) — downsample to display size, decode off main thread.
  4. 4.Main-thread work (JSON, I/O) — move to async/await pipelines; only touch UI on main.

Principles

  • One hypothesis at a time—profile, change one thing, compare traces.
  • Heavy feeds need budgets: max work per frame for decode + layout.
  • Identity (SwiftUI) and reuse (UIKit) wrong → extra rebuilds that feel like jank.

Load data in the background, create UIImage off main if needed, assign on MainActor.

Decode off the main actor (pattern)
Task {
    let data = try await loader.data(for: url)
    let image = await decodeOffMain(data)  // background
    await MainActor.run { imageView.image = image }
}

Follow-up angles

  • Signposts: os_signpost around cell configure and image apply to correlate spikes with code.