UI Testing & Debugging with Xcode Instruments
iOS Development — Architecture & Data
Chapter 7 · UI Testing & Debugging with Xcode Instruments
Chapter 6's own unit tests verify a ViewModel's own logic in isolation. This chapter covers two genuinely different real tools: UI testing, which drives the actual real app UI end to end, and Instruments, Apple's own real profiling suite for finding performance and memory problems a unit test can't catch.
UI Testing: A Genuinely Different Layer
Chapter 6's own tests never launch a real app — they test a ViewModel directly. UI testing (built on the real XCUITest framework) does the opposite: it launches the actual real app and drives it exactly as a user would, tapping buttons and reading real, rendered content.
Making Elements Findable: .accessibilityIdentifier()
XCUIApplication finds real UI elements by their accessibility identifier —
a stable, real string that doesn't change with localization or a later text edit, unlike matching on a
button's own visible label text.
Debugging with the Xcode Debugger
Beyond automated tests, Xcode's own real, built-in debugger — breakpoints, stepping through code, and the
console's real po (print object) command for inspecting a variable's own current value mid-run
— remains the genuinely fastest tool for understanding a single, specific bug as it happens.
Instruments: Real Performance & Memory Profiling
Instruments is Apple's real, dedicated profiling application, launched from Xcode via Product → Profile, running the real app while measuring what it actually does.
Real, sampled CPU usage — which functions are actually consuming the most processing time.
Every real memory allocation and its full lifecycle — genuinely the right tool for retain cycles.
Real, definite memory loss — allocated memory nothing can reach anymore at all.
TaskDetailView and back out, repeatedly, while watching Allocations' own real
memory graph. If the real memory count keeps climbing and never returns to its starting baseline, that's
a genuine, practical sign a retain cycle is keeping old TaskDetailView instances alive that
should have been deallocated.
Hands-On Exercises
Add real .accessibilityIdentifier() modifiers to TaskFlow's own "Add" toolbar button and the "Save" button inside NewTaskView, then write a real XCUITest function that launches the app, taps "Add," types a title, taps "Save," and asserts the new task's own title appears somewhere in the app.
Explain, in your own words, why a UI test finding a button by its real, visible label text ("Add") is genuinely more fragile than finding it by a real accessibility identifier ("addTaskButton"), giving one concrete, realistic scenario where the label-text approach would break.
📄 View solutionExplain, in your own words, why the Leaks instrument genuinely can't reliably detect a strong reference cycle, and why Allocations' own "memory that never shrinks back down" pattern is a real, practical signal of one instead.
📄 View solutionChapter 7 Quick Reference
- XCUITest launches and drives the real, actual app UI — a genuinely different layer from Chapter 6's own isolated ViewModel unit tests
.accessibilityIdentifier()gives real UI elements a stable, findable identity that doubles as a genuine accessibility improvement- The Xcode debugger (breakpoints,
po) remains the fastest real tool for understanding one specific bug live - Time Profiler measures real CPU usage; Allocations and Leaks measure real memory, but for genuinely different things
- Leaks catches definite memory loss only — Allocations, watching for memory that never shrinks back down, is the real, correct tool for finding strong reference cycles