Tutorials › Launch Lab Notes › Chapter 23

Full Res vs Thumbnails

LabChapter 23 of the Launch Lab Notes22 minAugust 20, 2026Intermediate

.resizable() shrinks what you see. It does not shrink what you keep.

Twelve procedural Harbor tiles. Three modes. phys_footprint on screen so the still does not need Instruments.

Filmstrip: EMPTY baseline, NAIVE live footprint jumps with 12×1536² bitmaps, THUMB drops near baseline with 96².

Empty — the baseline

-mode empty. No bitmaps.

MODE EMPTY. LIVE 18 MB phys_footprint. ACCOUNT 0.0 MB no bitmaps. NO BITMAPS.
MeterValue
LIVE18 MB
ACCOUNT0.0 MB

Naive — the control

-mode naive. Image(uiImage:) on twelve 1536×1536 bitmaps, drawn small in a grid. Accounted cost: 12 × 1536² × 4 = 108.0 MB. Decoded RGBA is also retained so pages stay dirty — otherwise the simulator under-reports.

MODE NAIVE. LIVE 236 MB. ACCOUNT 108.0 MB 12×1536²×4. Grid H1–H12 full-res tiles.
MeterValue
LIVE236 MB
ACCOUNT108.0 MB

Live sits above account because the bench holds both the UIImage and a retained RGBA buffer per tile — roughly two dirty copies plus the app baseline.

Thumb — downsample first

-mode thumb. Same twelve labels, generated at 96×96 before the view ever sees them.

MODE THUMB. LIVE 21 MB. ACCOUNT 0.4 MB 12×96²×4. Same H1–H12 grid visually.
MeterValue
LIVE21 MB
ACCOUNT0.4 MB

Visually the same grid. Accounted cost drops from 108.0 to 0.4. Live falls from 236 back near the empty baseline (21 vs 18).

Account vs live

ACCOUNT is arithmetic: pixels × 4 × count. LIVE is task_vm_info.phys_footprint. The first draft showed account jumping while live barely moved — UIImage alone had not dirtied enough pages. Retaining decoded RGBA made the live meter honest.

Mini-exercise

Change thumbSide from 96 to 256. Re-run -mode thumb and watch ACCOUNT become 12 × 256² × 4 ≈ 3.0 MB. Compare live to the 96² still.

Challenges

  1. Replace procedural tiles with PhotosPicker assets and keep the same three modes.
  2. Add a fourth mode that uses ImageRenderer / downsampled CGImage via CGImageSourceCreateThumbnailAtIndex.
  3. Plot live footprint every 200 ms into an on-screen sparkline while cycling.
  4. Purge with tiles = []; retainedRGBA = [] mid-cycle and confirm live returns near 18 MB.
  5. Wire XCUITest to assert ACCOUNT text contains 108.0 under -mode naive.

Key Points

Next up: Core Image and filters — a live filter chain on a still, each stage as a strip.

SwiftUI
SwiftUI tutorials for building native app screens, layouts, navigation, and state-driven interfaces.
Swift
Swift fundamentals for app developers who want to understand the language behind real iOS and macOS apps.
Ship iOS
Shipping workflows for iOS apps.
📚 Go deeper with LIPAI WANG’s hands-on Udemy bootcampsBrowse all courses →
← Ch 22: Same Feature, Three BodiesCh 24: Four Stages, One Still→
SwiftUIUltimate SwiftUI SeriesSwiftUI tutorials for building native app screens, layouts, navigation, and state-driven interfaces.SwiftUltimate Swift SeriesSwift fundamentals for app developers who want to understand the language behind real iOS and macOS apps.Ship iOSShip iOS Apps SeriesShipping workflows for iOS apps: signing, TestFlight, App Store Connect, CI, and release hygiene.

Ship your apps faster

When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.

Try Simple App Shipper
5 free articles remainingSubscribe for unlimited access