Figment.so
Mac hostingWebsite hostingGuidesHow to usePricing

Debug Leaks Using Xcode Memory Graph Remotely

If your iOS app's memory climbs with every navigation push and never drops back, the direct move is to run the app in the iOS Simulator on a hosted Mac, drive the suspect flow five or six times, then capture a memory graph. Because the Memory Graph Debugger needs a live Xcode GUI, pick a Figment plan whose confirmed access method shows you the Xcode window. A Figment M-series Mac from $95/month (specific chip, RAM and storage confirmed in the quote) is the natural fit for Xcode plus the Simulator plus screen sharing; the $29/month virtual Intel macOS VM runs a real macOS desktop over its browser console and is useful for Swift-package and command-line work, but the Simulator GUI workflow is more comfortable on physical Mac hardware. Apple's reference is Finding memory leaks with the Memory Graph Debugger, with background in Gathering information about memory use.

A retain cycle is a closed loop of strong references that keeps ARC from deallocating objects. The Memory Graph Debugger pauses your app and renders every live heap object as a node, so you can see exactly which references form the loop.

What the Memory Graph Debugger Captures

When you trigger a memory graph, Xcode freezes the running app and takes a snapshot of the heap. The snapshot includes every allocated object, its class, memory address and size, and the strong and weak reference edges connecting it to other objects.

The result is a node graph in the center panel. The navigator on the left lists objects grouped by type with instance counts. If Xcode detects a suspected cycle, it marks the involved nodes with a purple exclamation badge. The inspector on the right shows class name, address, size, and, when malloc stack logging is on, a backtrace of where the object was allocated.

A cycle appears as looping arrows between two or more nodes. A ViewController that holds a strong reference to a DataManager, while DataManager holds a strong reference back, produces exactly that loop. Neither object can be released, so both outlive the navigation pop.

Reaching the Remote Mac Desktop

You need a GUI session for the Memory Graph Debugger. Figment's physical Mac plans collect requests until supply is confirmed, so agree the remote-access method in the quote before you schedule the debugging work. Once your box is provisioned with screen sharing enabled, the typical client-side entry points are:

  • macOS Finder: ⌘K → vnc://your-mac-host
  • Windows: a VNC client such as RealVNC Viewer pointing at the same address
  • Linux: Remmina or TigerVNC

The iOS Simulator runs inside this GUI session, so you can build and launch the app, navigate through the screens that trigger growth, and pause for the graph in one remote window. An M-series Mac from $95/month gives Xcode, the Simulator and the remote-desktop stream room to breathe; the i3 Mac at $49/month also drives this flow on smaller projects. Exact chip, RAM and storage are confirmed in your configuration quote.

The $29/month virtual Intel macOS VM is reached through its browser console rather than screen sharing, and it has no GPU acceleration or audio. You can still open Terminal in that desktop and run the leaks CLI against a .memgraph captured elsewhere, which is useful for offline triage.

Triggering the Capture at Peak Memory

The right moment to capture is after the suspected leak has had time to accumulate, not at app launch. A reliable workflow:

  1. Build and run the app in the Simulator using a Debug configuration. Release builds strip type metadata the graph needs.
  2. Navigate into the screen you suspect — push the view controller, then pop it. Repeat five or six times.
  3. Watch the Memory gauge in Xcode's Debug navigator (⌘7). If memory never returns to its pre-push baseline, you likely have a cycle.
  4. Click the Debug Memory Graph button in the debug bar (the three-circle icon) to pause and capture. Check Xcode's Help menu for the exact keyboard shortcut in your installed version.

Capturing after several push/pop cycles means the objects that should have been released are the ones still present, instead of being drowned out by one-time launch allocations.

Reading the Graph: Strong, Weak, and the Cycle Root

In the graph view, solid arrows represent strong references and dashed arrows represent weak ones. A retain cycle always involves a closed loop of solid arrows. Select the purple-badged object in the navigator and trace its outgoing solid arrows in the center panel until they loop back.

A common Swift case: a closure stored as a property captures self strongly. The class holds the closure (strong), the closure holds the class (strong). Fix it with a [weak self] capture list. The Memory Graph shows this as a two-node loop with both arrows solid.

Also look for objects whose instance count in the navigator matches your push count exactly. If you pushed five times and see five PhotoDetailViewController instances alive, all five are leaked.

A Checklist for Each Memory Graph Session

Use this short list every time you investigate a leak on the remote Mac:

  • Debug build configuration — Release builds hide the type names you need.
  • Malloc stack logging on — Edit Scheme → Diagnostics → Malloc Stack Logging → Live Allocations. Required to see allocation backtraces in the inspector.
  • Reproduce the pattern — Push/pop or trigger the suspected operation at least 3–5 times before capturing.
  • Let memory settle — Wait a few seconds after the last action so deferred deallocations complete.
  • Filter the navigator by your module — Type your module name in the navigator search box to hide system objects.
  • Instance count matches iterations — Pushed 5 times and see 5 instances of one type? Leaked.
  • Trace every solid outgoing arrow from a suspect node until it loops back.
  • Export the graph before you change code so you have a before/after record.

Exporting .memgraph and Re-opening Offline

You do not have to fix the bug inside the same remote session. Use File → Export Memory Graph and save the .memgraph to the remote Mac's Desktop, then pull it down via the Finder's screen-sharing file transfer or your preferred SFTP client.

On any Mac with Xcode installed, double-click the .memgraph to reopen it in the debugger. You can also use the command-line leaks tool, which reads the same file:

leaks MyApp.memgraph
leaks MyApp.memgraph | grep -A 10 "PhotoDetailViewController"

Check leaks --help in your installed Xcode for the flags available in your version; options such as --fullContent vary over releases.

Headless Follow-up with leaks in CI

Once you know which type to watch, you can run leaks against the simulator process in CI without a GUI session:

# After your tests boot the simulator and launch the app:
xcrun simctl spawn booted leaks com.example.MyApp > leaks-report.txt

Treat a non-zero exit from leaks as a failure and keep the report as a build artifact. You do not get the visual graph this way, but you do get class names and reference chains in text — a good gate once a known cycle has been fixed, so it does not quietly return.


A hosted Mac gives you the persistent Xcode session needed to run repeated push/pop cycles and capture the graph at the right moment. Figment M-series Macs from $95/month handle Xcode, Simulator and remote desktop together — confirm the specific hardware and screen-sharing access in the quote. Request a configuration or get started now.

Related guides:


Subscribe for Figma design and website publishing guides.


Figment.so

Contact

Twitter

Website pricing

Compute index

About

Privacy

Terms