Open-source project
daisuke0131/ViewMonitor avatar
daisuke0131/ViewMonitor

ViewMonitor: an in-app layout inspector for UIKit and SwiftUI

An in-app visual layout inspector for iOS. Inspect UIKit and SwiftUI views, frames, spacing, overlaps, insets, and properties on device.

721 stars46 forksSwiftMIT

At a glance

What is it?
ViewMonitor puts a measurement overlay inside your running iOS app so you can read frames, gaps and insets without attaching Xcode's View Debugger. It works on UIKit and on the accessibility elements SwiftUI publishes, but the SwiftUI side is thinner than the table suggests.
Who is it for?
Adopt ViewMonitor if your layout bugs are geometric (spacing, overlap, containment) and you want to check them on a device without a debugger session. Skip it if your SwiftUI work depends on reading font, background, alpha or corner radius, because the README's own table marks those as not available for SwiftUI.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 37 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap ViewMonitor fills between design spec and running app

Xcode's View Debugger captures a snapshot of the view hierarchy and lets you inspect it after the fact. That workflow breaks down when the question is relational: how far apart are these two elements, do their frames intersect, how much padding sits between a container and its child. Reading those numbers out of a captured hierarchy means clicking through nodes and doing arithmetic. ViewMonitor moves the measurement into the app itself. The README frames the goal as inspecting UIKit and SwiftUI layouts "directly inside your app", and one of its stated reasons is to "compare a design specification with the implementation directly on a simulator or device". That is the audience: iOS engineers doing design QA, and anyone chasing a spacing bug that only reproduces in a particular state of a running screen. The package targets iOS 15.0 and later, Xcode 26.0 and later, and Swift 6.0, so it is aimed at projects already on a recent toolchain rather than teams maintaining older deployment targets.

How measurement mode captures and freezes the screen

The mechanism is an overlay of buttons, one per detected element. You tap the ViewMonitor button in the top-right corner to enter measurement mode, then tap overlay buttons to select elements. Selection is a two-step gesture: pick one element, pick another, and the info panel describes the relationship. The first element gets a blue outline, the second a red one. The panel then reports gapX and gapY when the frames are separated, overlapX and overlapY when they intersect, and top, left, bottom, right when one frame contains the other. Those values are computed from the frames as they exist in the running app, which is why the same flow covers UIKit-to-UIKit, SwiftUI-to-SwiftUI, and mixed UIKit-to-SwiftUI pairs.

The deliberate design choice is that measurement mode blocks touches from reaching the app. The README says this prevents "accidental navigation, actions, or scrolling", and that overlay buttons stay at the positions captured when measurement started. Rotation and programmatic screen changes keep measurement mode on, re-scan the new screen, and clear the previous selection. The cost of that freeze is explicit in the docs: to reach a different state you turn measurement mode off, move the app there, then turn it on again. If the bug only appears mid-scroll or during a transition, the tool cannot hold the interaction and the measurement at the same time.

SwiftUI inspection rides on the accessibility tree

SwiftUI does not expose a view hierarchy the way UIKit does, so ViewMonitor reads the accessibility elements SwiftUI publishes for Text, Image, Button, list rows and other accessible content. The docs are clear that iOS builds that tree only while an accessibility client is active, and that ViewMonitor.enableSwiftUIElementDetection() activates it from inside the process, so you do not need VoiceOver or Accessibility Inspector attached. That helper relies on a private accessibility API. It is compiled into debug builds only, is a no-op returning false in release builds, and the private symbol names are not included in the binary. The stated fallback is to attach Xcode's Accessibility Inspector or enable VoiceOver and reopen the screen.

This is the part of the project with the most visible seams. The README's capability table marks background, alpha and corner radius as not available for SwiftUI, and font family, size and color likewise. Position, size, element type and published text are what you get. Two further behaviours follow from the accessibility dependency: a view using .accessibilityElement(children: .combine) is measured as a single element, and a view using .accessibilityHidden(true) is not detected at all. If your SwiftUI screens lean on either modifier, expect the overlay to disagree with what you see on screen. The README does note that when ViewMonitor finds SwiftUI content but no accessibility elements, the info panel shows instructions rather than failing silently, which is the right call for a debugging aid.

Adding it to a project: the actual entry points

Installation is a standard Swift Package Manager dependency on https://github.com/daisuke0131/ViewMonitor.git, or via File > Add Package Dependencies in Xcode. The README also lists CocoaPods distribution. For SwiftUI, the pattern is to call ViewMonitor.enableSwiftUIElementDetection() in the App initializer and attach .viewMonitor() to the root view inside WindowGroup. For UIKit, it is a single ViewMonitor.start() call from the scene delegate's scene(_:willConnectTo:options:), after the app has a window. There is no configuration file, no plist key and no environment variable documented, which keeps the integration surface small.

The repository ships two runnable examples, Example/ViewMonitorSwiftUIExample and Example/ViewMonitorExample, and the README says both run on the simulator as-is. For a physical device you create a git-ignored Local.xcconfig next to the example and set DEVELOPMENT_TEAM, with the exact echo commands given in the README. That is a detail worth noticing: the device path is documented only for the bundled examples, not as general guidance for your own app, so on-device use in a real project is something you would have to wire up yourself.

Where the accessibility dependency becomes a failure mode

The sharpest limitation is not the missing font or color data. It is that SwiftUI detection depends on a private API, which makes it fragile against OS changes in a way that ordinary public API usage is not. The project mitigates this by compiling the helper into debug builds only, so a release binary carries none of the private symbols and an App Store submission is not exposed to them. That mitigation is sound, but it also means the feature can only ever be a development-time tool. There is no supported path to shipping ViewMonitor's SwiftUI detection in a release build, and the README does not suggest one.

The second failure mode is coverage. Because detection is accessibility-driven, a SwiftUI element that is not accessible is invisible to the overlay. Decorative views, custom drawing, and anything hidden from accessibility simply do not appear. A UIKit engineer used to the View Debugger's complete hierarchy will find this narrower than expected. The README is honest about it, listing the combine and hidden cases under SwiftUI limitations rather than leaving them to be discovered, but it is still the reason the SwiftUI column of the capability table is shorter than the UIKit one.

ViewMonitor against Xcode's View Debugger and Accessibility Inspector

The obvious alternative is the tooling Apple already ships. Xcode's View Debugger gives you the full UIKit hierarchy, including views ViewMonitor's accessibility-based detection would never see, and it works without adding a dependency to your app. Accessibility Inspector shows the same accessibility tree ViewMonitor reads for SwiftUI, and the README names it as the fallback when the private helper is not active. The difference in approach is where the numbers are computed. Both Apple tools inspect a captured or externally observed state; ViewMonitor computes gap, overlap and containment insets live, from the frames in the running process, and presents them as a relationship between two elements you tapped. That relational measurement is the part that is tedious to reconstruct by hand in the View Debugger, and it is the reason to add a package rather than reach for the built-in tools. If your questions are about individual view properties rather than the space between views, the built-in tools cover more ground and cost nothing to adopt.

Licence, maintenance and what to check before adopting

ViewMonitor is MIT licensed, which permits commercial and closed-source use with the usual requirement to retain the copyright and permission notice. This is not legal advice; read the LICENSE file in the repository if the terms matter to your organisation. The release cadence visible in the supplied material is active: 2.4.0, 2.3.0 and 2.2.0 all landed within a few days of each other in August 2026, and the last push to master is dated the same day as the 2.4.0 release. Frequent releases on a small tool can mean either responsive maintenance or churn in the integration surface. The README documents no migration notes between 2.x versions, and the package dependency example pins from: "2.0.0", so a minor bump could in principle change behaviour your overlay depends on. Pinning to an exact version in Package.swift is the cheap insurance here.

Before adopting, verify two specific things in your own codebase. First, that ViewMonitor.enableSwiftUIElementDetection() produces tappable elements on your actual screens, since the combine and hidden accessibility modifiers will silently reduce coverage. Second, that the root .viewMonitor() modifier coexists with whatever accessibility configuration your app already applies, because the helper activates the accessibility tree from inside the process and the interaction between the two is not documented. Both checks are quick, and both are cheaper than discovering the limitation after you have built a QA workflow around the overlay.

Editorial conclusion

Adopt ViewMonitor if your layout bugs are geometric (spacing, overlap, containment) and you want to check them on a device without a debugger session. Skip it if your SwiftUI work depends on reading font, background, alpha or corner radius, because the README's own table marks those as not available for SwiftUI. Before you commit, verify two things in a scratch branch of your own app: that ViewMonitor.enableSwiftUIElementDetection() actually produces tappable elements for your screens, and that the root .viewMonitor() modifier does not disturb your existing accessibility configuration.

Official sources

  1. daisuke0131/ViewMonitor on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Community notes

Community notes