Integrating Reveal without modifying your Xcode project

So you use Reveal and you love it. But you’ve just fired up a new app in Xcode’s debugger and you want to have a quick look at the internals of the app’s view hierarchy, but you haven’t integrated Reveal via the static or dynamic library yet. What to do?

No problem! LLDB to the rescue.

LLDB can execute arbitrary code inside your running application. So you can just load Reveal into any iOS process you are currently debugging.

Just hit ^⌘Y to pause the iOS app in the Xcode debugger and then at the (lldb) prompt type:

LLDB Commands

expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2);
expr [(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
continue

Simple, right?

OK, so maybe not so simple and easy to remember. Wouldn’t it be better if we could just type reveal_load at the LLDB prompt or something like that?

Well, we can! LLDB supports command aliases. Just like with bash, you can create an alias in LLDB for a more complex command. The syntax is a bit different but the concept is the same. Also, just like bash, LLDB has a ‘dot file’ that it loads every time it starts which is the ideal place to put your LLDB command alises. That dot file is ~/.lldbinit.

Open up your favourite text editor, create the file .lldbinit file in your home directory and chuck the following LLDB command aliases into it:

~/.lldbinit

command alias reveal_load_sim expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2);
command alias reveal_load_dev expr (void*)dlopen([(NSString*)[(NSBundle*)[NSBundle mainBundle] pathForResource:@"libReveal" ofType:@"dylib"] cStringUsingEncoding:0x4], 0x2);
command alias reveal_start expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
command alias reveal_stop expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStop" object:nil];

The above snippet creates four command aliases: reveal_load_sim, reveal_load_dev, reveal_start and reveal_stop.

Note: *Invoking the reveal_start command is only required if you invoke one of the reveal_load commands after iOS has posted the UIApplicationDidFinishLaunchingNotification notification. i.e. After your application delegate has handled application::didFinishLaunchingWithOptions:.

With these aliases defined you can now issue these quick commands at the LLDB prompt in Xcode. LLDB even auto-completes them for you!

Reveal LLDB Command Aliases

Reveal LLDB Command Aliases

Ok so now you have some quick LLDB command aliases and can trigger them manually, how do you make it more automatic?

Breakpoints

Xcode (LLDB really) can execute commands in response to breakpoints. Using this knowledge we can add breakpoints to our application that load and start Reveal automatically.

Reveal Breakpoint Commands

Reveal Breakpoint Commands

The image above shows how you can add the Reveal LLDB commands to a break point in Xcode.

Some things to note about this breakpoint:

When the breakpoint commands are successfully executed by LLDB you will see something like the following in the debugger console:

(void *) $0 = 0x0000000109022350
2013-11-07 15:18:20.687 Test[18049:70b]  INFO: Reveal server started.

Now you’re armed with LLDB and Reveal super powers!

Written by
Oliver Jones — Oliver is the Technical Director at Itty Bitty Apps. You can follow him on Twitter @orj.