Watchpoint — what it is, types and configuration of watchpoints in Xcode

Author: IT Sectr Published: 2026-05-07 Reading time: 8 min

Watchpoint (observation point) — a debugging mechanism that pauses program execution when the value of a specified variable or memory region changes. Unlike a breakpoint, which is tied to a line of code, a watchpoint tracks data changes regardless of where in the program the modification occurs. According to Apple Developer Documentation, watchpoints are indispensable for debugging data races, unexpected property changes, and tracking object lifecycles.

Key Takeaways

  • Watchpoint — a point monitoring a variable for changes, triggered on any write to the specified memory region.
  • Xcode supports watchpoints via GUI and LLDB console, including conditional watchpoints.
  • Property variables of objects require a watchpoint with the memory address rather than the variable name.
  • Performance with watchpoints degrades significantly due to hardware monitoring of each write operation.
  • Watchpoints are not preserved between debugging sessions — they must be set again after each launch.

What is a watchpoint and how it works

Watchpoint — is a debugger mechanism that pauses program execution when the value at a specified memory address changes. If a breakpoint reacts to reaching a specific line of code, a watchpoint reacts to writing to a specific memory cell — regardless of which part of the code performed the write. This makes it indispensable for finding unexpected variable modifications, especially in multithreaded applications.

The working principle is based on hardware processor support. Modern ARM chips (Apple Silicon, Qualcomm Snapdragon) provide 4 to 8 hardware watchpoint registers. When the processor executes a write instruction to an address matching a watchpoint, a hardware interrupt occurs, which the debugger catches. When hardware registers run out, LLDB switches to software mode — it step-checks every write instruction, slowing execution by tens of times.

According to the ARM Architecture Reference Manual, hardware watchpoints operate at the Data Watchpoint and Trace (DWT) module level and do not require modification of executable code. The response time is in nanoseconds, allowing tracking even high-frequency variable changes in data processing loops such as audio or video frame buffers.

When a watchpoint is more effective than a breakpoint

Watchpoint is indispensable when you know which variable is changing but not where from. Typical scenarios: a UIView frame property changes without apparent reason; a counter in a background thread resets unpredictably; an isLoading flag switches before a network request completes. In each of these cases, setting breakpoints at all places where a write could occur is impractical. A watchpoint solves the problem with a single command.

Types of watchpoints and how to set them

Xcode and LLDB support three types of watchpoints: watchpoint set variable — for monitoring a local variable; watchpoint set expression — for monitoring an expression that returns an address; watchpoint set — for monitoring a raw memory address. Each type has its own area of application.

Watchpoint typeLLDB commandUsage
Variablewatchpoint set variable -w write self.countLocal and global variables, struct properties
Expressionwatchpoint set expression -w write -- &self->mutex.lockStruct fields by pointer, array elements by index
Addresswatchpoint set -w write 0x600000c4b80Specific memory address from previous LLDB output

Setting via Xcode GUI

In Xcode, you can set a watchpoint via the Debug Area: pause at a breakpoint, find the desired variable in the Variables View panel, right-click and select Watch Variable. Xcode will automatically execute the watchpoint set variable command with the correct variable name and context. After that, the debugger will pause on every value change — convenient for quick debugging without switching to the console. However, this method only works while the variable is in scope of the current frame.

swift
func processItems(_ items: [String]) {
    var index = 0
    // Set watchpoint on index via GUI:
    // pause here, right-click → Watch Variable
    for item in items {
        index += 1
        print("Item \(index): \(item)")
    }
}

Managing watchpoints via LLDB

LLDB provides a full set of commands for managing watchpoints from the console. This gives more control than the GUI: you can set the observation region size, specify trigger conditions, create watchpoints on addresses obtained from computed expressions, and automatically execute actions on trigger. The command interface is especially useful when debugging complex scenarios that require quickly changing observation parameters.

Basic watchpoint commands

The watchpoint set variable command takes a variable name with scope consideration: for Objective-C self-properties use self->_property, for Swift use self.property. The -w write parameter sets write tracking, -w read — read tracking (a mode only available on some architectures), -s size — the region size in bytes. After setting a watchpoint, you can view the list with the watchpoint list command.

lldb
(lldb) watchpoint set variable -w write -s 8 self.balance
Watchpoint 1: addr = 0x600000c4b80 size = 8 state = enabled  type = w
    watchpoint spec: 'self.balance'
(lldb) watchpoint set expression -w write -- self->items._storage
Watchpoint 2: addr = 0x600003a4c00 size = 8
(lldb) watchpoint list
1: location = 0x600000c4b80, type = write, variable = '_balance'
2: location = 0x600003a4c00, type = write, expression = 'self->items._storage'

Conditional watchpoints

Like breakpoints, watchpoints support conditional triggering. The -c parameter sets a condition in Swift or Objective-C. For example, a watchpoint with the condition newValue > 1000 will only stop when the written value exceeds one thousand. This is critical when debugging loops or sensors generating thousands of changes per second — otherwise the debugger would stop on every change, making work impossible.

lldb
(lldb) watchpoint set variable -w write self.temperature -c "(int)$newValue > 100"
Watchpoint 3: addr = 0x600000e4a20, condition = '(int)$newValue > 100'
(lldb) watchpoint modify 3 -C "po self.temperature" -G true
// Automatically log value and continue execution

Watchpoints for object properties and collections

A specific feature of watchpoints for Objective-C and Swift object properties — a watchpoint is set not on the property name but on the address of the ivar (instance variable) field in the object’s memory. This means that with each new object allocation (e.g., when recreating a ViewController), the watchpoint becomes invalid because the memory address has changed. For persistent monitoring of a property across restarts, you need to re-set the watchpoint at the moment of object initialization.

Watchpoint on collection elements

Monitoring elements of arrays and dictionaries requires computing the address of a specific element. For example, to monitor the third element of an array use watchpoint set expression -- &array[2]. If the array reallocates its internal buffer (when adding elements beyond capacity), the watchpoint becomes invalid — LLDB will report an error Watchpoint 1 has an invalid address. In such cases, you need to re-set the watchpoint after changing the collection size.

lldb
(lldb) expr var $arr = [10, 20, 30, 40, 50]
(lldb) watchpoint set expression -w write -- &$arr[2]
Watchpoint 4: addr = 0x1000a4b20, size = 8
(lldb) expr $arr[2] = 99
Watchpoint 4 hit: old value: 30, new value: 99

Tracking retain count via watchpoint

In Objective-C, you can track an object’s retain count by setting a watchpoint on the retainCount field in the objc_object structure. LLDB does this via watchpoint set expression -w write -- (int*)[object retainCount]. However, for Swift objects with ARC (Automatic Reference Counting), retain count is not directly accessible — instead use Instruments or the Memory Graph Debugger for leak analysis. According to Apple, watchpoints on retain count only work in Debug builds with ARC optimization disabled.

Limitations and performance of watchpoints

Watchpoints have several important limitations to consider. The main one — the number of hardware watchpoints is limited to 4–8 registers on ARM architecture and up to 4 on x86. When all hardware registers are occupied, LLDB switches to software watchpoint mode: it modifies every write instruction in the tracked range to generate an exception. This slows execution by 10–50 times, so in practice it’s recommended to use no more than 2–3 active watchpoints simultaneously.

The second limitation — invalidation of watchpoints upon memory reallocation. When garbage collection or ARC triggers, and an object moves in memory (in languages with heap compaction), the watchpoint address becomes incorrect. In Swift and Objective-C, ARC does not move objects, but array and string reallocation causes the same effect. LLDB warns about this with the message Watchpoint N address (0x...) doesn’t contain a valid allocation.

The third limitation — variable visibility. A watchpoint on a local variable only works while that variable is within the scope of the current stack frame. Once the function exits, the watchpoint is automatically removed. For monitoring global variables or fields of long-lived objects, a watchpoint persists until explicitly deleted via watchpoint delete or until the process terminates.

lldb
(lldb) watchpoint delete 1
1 watchpoints deleted.
(lldb) watchpoint delete               # Delete all watchpoints
2 watchpoints deleted.
(lldb) watchpoint disable 1             # Temporarily disable
(lldb) watchpoint enable 1              # Enable again

According to ARM, watchpoints on Apple Silicon (M1–M4) support a monitored region size from 1 to 8 bytes. For monitoring structures larger than 8 bytes, you need to set multiple watchpoints on each field. This is important when debugging complex data structures such as CGRect (16 bytes) or UIEdgeInsets (16 bytes).

Frequently Asked Questions

What is the difference between a watchpoint and a breakpoint?

Breakpoint is tied to a line of code — it stops when that line is reached. Watchpoint is tied to a memory address — it stops when a write occurs to that address from anywhere in the program. A watchpoint looks for “who is changing the value,” a breakpoint looks for “what happens on this line.”

How many watchpoints can be set simultaneously?

4–8 hardware watchpoints on ARM (including Apple Silicon). Exceeding this switches the watchpoint to software mode, slowing execution by 10–50 times. It is recommended to use no more than 2–3 active watchpoints at a time.

Why does a watchpoint stop working after restarting the application?

Watchpoints are not preserved between debugging sessions. On each new launch, memory addresses change, and the watchpoint must be set again. The exception is watchpoints on global variables with a fixed address.

Can I set a watchpoint on a Swift property?

Yes, but the watchpoint is set on the ivar (backing storage) of the property, not on the property itself. In Swift, use watchpoint set variable self.property — LLDB will automatically find the corresponding ivar by property name.

How does a watchpoint affect application performance?

Hardware watchpoints do not affect performance — the interrupt happens at the processor level. Software watchpoints (when hardware registers are exhausted) slow execution by 10–50 times, as LLDB checks every write instruction.

Summary

  • Watchpoint — a point monitoring memory changes, triggered on any write to the specified address from any thread.
  • Hardware watchpoints use processor DWT registers and do not slow execution, but are limited to 4–8 registers.
  • LLDB supports three types of watchpoints: on a variable, on an expression, and on a raw memory address.
  • Conditional watchpoints only trigger when a specified expression evaluates to true — essential for debugging high-frequency changes.
  • Watchpoints on object properties and collection elements become invalid upon memory reallocation.
  • Watchpoints are not preserved between sessions and are removed when a variable goes out of scope.
  • Watchpoint is the best choice when the variable is known but the place of its modification is not, especially in multithreaded code.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also