Debugging Applications With Reveal

Resources

In Debugging Applications With Xcode, we explored Xcode's built-in view debugger. While I occasionally use Xcode's view debugger to debug user interface issues, I mostly use Reveal, a third party application developed and maintained by Itty Bitty Apps. In this episode, I show you how Reveal compares to Xcode's built-in view debugger and why I prefer Reveal over Xcode to debug user interface issues.

Before we start, I need to mention that Reveal is a paid application. This episode isn't sponsored by Itty Bitty Apps and I don't receive a kickback if you purchase Reveal. Reveal is a fantastic application that you need to know about. It's as simple as that. The application is under active development and Itty Bitty Apps releases bug fixes and new features on a regular basis. You can try Reveal for free by visiting its website.

Integrating Reveal

Let's start with Reveal's most important drawback. Apple's view debugger is built into Xcode and that means you can fire up the view debugger with a single click. That isn't true for Reveal. To inspect an application with Reveal, you need to link the application with the Reveal Server framework. That's very easy to do, though, and Reveal offers several options.

I almost always use CocoaPods. It's the simplest solution if you use CocoaPods as your dependency manager. You can also manually link the Reveal Server framework into your application if you don't use CocoaPods. Another option is loading the Reveal Server framework via a breakpoint in Xcode. This option is interesting if you don't want to modify your project. Each of these options is covered in detail in Reveal's integration guide.

Let me show you how easy it is to integrate Reveal using CocoaPods. Install Reveal and download the starter project of this episode if you'd like to follow along. I'm going to show you how to integrate Reveal into Cloudy, a simple weather application that uses CocoaPods to manage its dependencies.

Open the project's Podfile and add Reveal as a dependency of the Cloudy target.

pod 'Reveal-SDK'

It's important that you only link your application with the Reveal Server framework in development. CocoaPods makes this easy. Dependencies are by default linked into builds of your application for every configuration of the target. We can override this behavior by specifying which configurations a dependency needs to be enabled for. For Reveal, we specify in the project's Podfile that it should only be linked into builds of your application that are compiled using the Debug configuration.

pod 'Reveal-SDK', configurations: ['Debug']

Run the pod install command to install the dependencies specified in the Podfile.

pod install
Analyzing dependencies
Downloading dependencies
Installing Reveal-SDK (14)
Using RxBlocking (4.0.0)
Using RxCocoa (4.0.0)
Using RxSwift (4.0.0)
Using RxTest (4.0.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 5 dependencies from the Podfile and 5 total pods installed.

That's it. Open Cloudy.xcworkspace in Xcode and run the application to make sure we successfully integrated Reveal into Cloudy. Open Xcode's console and inspect the output. Reveal Server logged a message to the console, indicating that we can inspect the application using Reveal.

Cloudy[61563:744798]  INFO: Reveal Server started (Protocol Version 43).

It's time to launch Reveal. Reveal automatically detects and lists the applications it can inspect. Every application running Reveal Server can be inspected if it runs in the simulator or, if you've deployed your application to a device, if it's accessible over Wi-Fi or USB. Because I'm running Cloudy on a device connected over USB, Reveal gives me the option to connect over Wi-Fi or USB.

Debugging Applications With Reveal

Connecting over USB is fast and convenient if your development machine or your device isn't connected to a Wi-Fi network.

Exploring Reveal

The first thing you see is Reveal's beautiful, focused user interface. It sports a dark look that feels familiar if you've worked with Xcode's view debugger. Let's take a closer look at Reveal's user interface.

Reveal's Beautiful and Focused User Interface

View Hierarchy

As in Xcode's view debugger, the view hierarchy of your application is visible on the left. Reveal shows you only what's useful and it makes clever use of icons, colors, and transparency. Views that are hidden or not visible are slightly dimmed. Each UIKit component has its own icon in the view hierarchy on the left, which makes navigating the view hierarchy fast and more efficient.

View Hierarchy

Finding a user interface element is quick and easy with the search bar at the bottom. Like Xcode's view debugger, Reveal's search bar is smart. Enter a few characters and chances are that Reveal shows you what you're looking for. You can even search for the text of a label or the title of a button.

Reveal's Powerful Search Capabilities

You can also specify what your query needs to match, such as class name, accessibility label, or view tag. You can even search for a memory address.

Reveal's Powerful Search Capabilities

What I like most is how the search results are presented to the user. The search results are visible in the view hierarchy, but they're also highlighted in the canvas. Reveal includes neighboring views to provide more context.

Reveal's Powerful Search Capabilities

Canvas

Reveal's canvas is a gorgeous display of what a dedicated development tool can look like. It shows a beautiful three-dimensional view of your application's view hierarchy.

Reveal's Main Window or Canvas

Reveal gives you a few options to control what's visible in the canvas. As in Xcode's view debugger, you can ask Reveal to only display the frames of the views in the view hierarchy, their contents, or both frames and contents. The latter is what you'll find yourself using most often. Only showing frames is useful if you're inspecting the constraints of a view or if you're debugging Auto Layout issues.

Frames, Contents, or Both Frames and Contents

You can switch between a two-dimensional and a three-dimensional rendering of your application's view hierarchy. Even though the three-dimensional view looks appealing, remember from Debugging Applications With Xcode that the two-dimensional view has its benefits. For example, the two-dimensional view is very convenient if you need to inspect the alignment of several views.

You can switch between a two-dimensional and a three-dimensional rendering of your application's view hierarchy.

The three buttons on the right of the search bar allow you to control what's being rendered by Reveal. You can show or hide constraints and layout guides in the view hierarchy on the left by toggling the first button.

The three buttons on the right of the search bar allow you to control what's being rendered by Reveal.

The middle button shows or hides system views. If you enable this option, the status bar appears at the top. Notice that the status bar lives in its own window. That's why it's always laid on top of your application's view hierarchy.

The middle button shows or hides system views.

The button on the right shows or hides hidden views. Remember from Debugging Applications With Xcode that this option comes in handy to debug user interface issues.

The slider in the bottom right allows you to zoom in and out. This is useful, but it's faster and more convenient to scroll and press the Command key. The button on the right of the slider resets the canvas.

The slider in the bottom right allows you to zoom in and out.

Like Xcode's built-in view debugger, you can focus on a view or collection of views by double-clicking a view in the canvas or the view hierarchy on the left.

You can focus on a view or collection of views by double-clicking a view in the canvas or the view hierarchy on the left.

Notice that Reveal animates the transition. This may seem like a gimmick, but it really isn't. When you're working in a complex view hierarchy, these subtle visual cues add context and they're incredibly helpful.

Focusing on one or more views is one option to remove clutter. Another option is collapsing the view hierarchy on the left. Reveal flattens collapsed views in the three-dimensional view to help you focus on what matters.

Another option is collapsing the view hierarchy on the left.

The jump bar at the top of the window behaves slightly differently from the jump bar in Xcode's view debugger. You can use the jump bar in Reveal to step through the view hierarchy, changing the scope of the focus.

You can use the jump bar in Reveal to step through the view hierarchy.

Last but not least, the focus history buttons on the left of the jump bar allow you to traverse your focus history. They're similar to the Go Back and Go Forward buttons in Xcode.

Inspectors

Application Inspector

Reveal includes a range of inspectors on the right. The first inspector, the Application Inspector, displays information about the application, such as its identifier for vendor, the name and model of the device, and the version of the operating system.

Application Inspector

You can obtain this information through Apple's SDKs, but having this information at your fingertips is convenient at times.

Identity Inspector

Reveal populates the Identity Inspector the moment you select a view in the view hierarchy or the canvas. It shows a bunch of properties that are related to the current selection, such as the view controller that manages the selected view, its class, and memory address.

Identity Inspector

As a (freelance) developer, you occasionally need to work on projects you're not familiar with. Reveal has helped me countless times with this sometimes daunting task. Reveal makes it easy to figure out which view controller a view belongs to. It's a fast and efficient technique to browse a codebase you're not familiar with.

I have to admit that I miss the view controller banners Xcode displays in the view debugger. I hope that feature makes it into Reveal some day.

Attributes Inspector

Reveal's Attributes Inspector is one of the features that sets it apart from Xcode's view debugger. The view debugger built into Xcode shows you some of the attributes of the currently selected element. Reveal takes it a few steps further. It lists more attributes and, more importantly, most of them are editable.

Attributes Inspector

This is only possible because Reveal doesn't interrupt the execution of your application. Remember that Xcode pauses the execution of your application to capture a snapshot of your application's view hierarchy. Any change you make in Reveal is reflected in the canvas as well as on the device or in the simulator.

Layout Inspector

The Layout Inspector summarizes the layout properties of the currently selected view, including its frame, bounds, and constraints. Most of the attributes are editable, which means you can make live changes to the layout properties of the currently selected view.

Layout Inspector

This is very powerful. Let me show you what I mean. Switch to Reveal's two-dimensional view, select the windspeed label of one of the table view cells, and set its horizontal content hugging priority to 251. Because the horizontal content hugging priority of the temperature label is also set to 251, this change results in an ambiguous layout.

Ambiguous Layout

Reveal evaluates the changes, spots the problem, and warns us that it detected an issue. Reveal displays the layout issue in the Layout Inspector if you click the small yellow triangle in the view hierarchy. Even though Reveal doesn't make suggestions to resolve the layout issue, it's clear that Reveal is a very helpful tool to debug Auto Layout issues.

Ambiguous Layout

Layer Inspector

The inspector on the right is the Layer Inspector. As the name implies, it shows the properties of the backing layer of the currently selected view.

Layer Inspector

Speed, Performance, and Reliability

Some of the most important features of Reveal aren't immediately obvious. They become visible once you've worked with Xcode's view debugger for a while. Reveal is fast, performant, and very reliable. I can't remember the last time Reveal failed on me. This is obviously the result of a committed development team and the frequent updates.

It can often take several seconds or longer for Xcode's view debugger to capture a snapshot of the view hierarchy and sometimes it fails without a clear reason. This doesn't happen often, if ever, when you're working with Reveal.

Unable to Capture View Hierarchy

Reveal also has the upper hand in terms of debugging Auto Layout issues. Let me show you what I mean. Revisit the project in Xcode and open WeatherDayTableViewCell.swift. In awakeFromNib(), we fix the width of iconImageView to 100 points.

override func awakeFromNib() {
    super.awakeFromNib()

    // Configure Cell
    selectionStyle = .none

    // Fix Width to 100 Points
    iconImageView.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
}

Run the application and refresh the snapshot in Reveal by clicking the refresh button in the status view, choosing View > Refresh from the menu, or pressing Command + R.

Refresh Snapshot

Reveal displays Auto Layout warnings and errors. Warnings, which we covered a few moments ago, are similar to the runtime issues reported by Xcode's built-in view debugger. They indicate that the layout is ambiguous. As you may remember from Debugging Applications With Xcode, errors are not reported by Xcode's view debugger. They indicate that a layout is unsatisfiable and one or more constraints were broken to satisfy the layout.

The layout engine doesn't like the change we made in the WeatherDayTableViewCell class. We set the width of the image view to 60 points in Interface Builder, which conflicts with the constraint we added in code. The output in Xcode's console confirms this.

Cloudy[6800:248704] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x608000288700 UIImageView:0x7fdf00418ab0.width == 60   (active)>",
    "<NSLayoutConstraint:0x608000288e30 UIImageView:0x7fdf00418ab0.width == 100   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x608000288e30 UIImageView:0x7fdf00418ab0.width == 100   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

Xcode's view debugger doesn't report these types of errors, but Reveal does. The error shows up as a small red triangle in the view hierarchy on the left, indicating that Auto Layout encountered an error. The layout is unsatisfiable and one or more constraints were broken to satisfy the layout.

Unsatisfiable Layout

If we click the small red triangle, the list of constraints expands and the Layout Inspector on the right opens. Notice that the Layout Inspector is badged with a small red triangle to indicate that Reveal encountered one or more errors.

Unsatisfiable Layout

Reveal informs us that the constraint we selected has been broken by the layout engine because it couldn't be satisfied. That's also what Xcode reports in the console. The difference is that Reveal highlights the problematic constraints in the view hierarchy, making it much easier to debug the issue.

And More

Even though I showed you in this episode how to use Reveal to debug an iOS application, Reveal also supports tvOS applications and app extensions. The developers also told me that Reveal has rudimentary support for watchOS applications.

Some of Reveal's features illustrate the amount of effort the team has put into the application. For example, it's possible to save a view hierarchy to a file, which can be useful if you're working in a team or if you want to revisit a snapshot at a later point. Reveal supports multiple tabs and windows, which make it easy to compare view hierarchies side by side.

Reveal integrates nicely with Touch Bar and it has built-in support for AppCode. The application continues to improve with every release and it's worth the investment. Download Reveal and give it a try.

Resources

Stop Writing Swift That Sucks

Download the Swift Patterns I Swear By