Reveal Integration Guide

TL;DR

WARNING: Don’t ship or link the Reveal library with your release builds. Typically this means you should only link the Reveal library in a target’s Debug build configuration.

If you have any problems integrating Reveal with your application check the detailed instructions below. If you’re still having problems or have questions, head over to our support site.

Table of Contents

  1. Introduction
  2. Static Library Framework Integration
  3. Dynamic Library Integration
  4. Cocoapods Integration
  5. Important Notes

Introduction

To inspect your iOS application with Reveal you must first link the application with the Reveal library, which is packaged within the Reveal application. To find the library:

  1. Launch Reveal
  2. Open the Help menu
  3. Select Show Reveal Library in Finder

This will open a Finder window showing a folder named “iOS-Libraries”. The folder contains the following files:

WARNING: Neither type of library should be shipped with the release build of your application. Reveal exposes your app to deep introspection and will likely cause your app to be rejected by the Apple review team. Reveal is intended for internal development and debugging purposes only.

Reveal offers three options for integrating the library with your iOS application:

Static linking

Statically linking library frameworks is the most common way to integrate third party libraries into iOS apps and should be familiar to many iOS developers. Detailed instructions on how to modify your project to statically link the Reveal library are included below.

Dynamic loading

Dynamic loading allows third party libraries to be loaded into an iOS application on demand, at runtime. In this scenario the library is not linked in to the executable. The dynamic library is included in the app bundle and can be loaded on demand. This approach allows developers to maintain full control over when the Reveal library is loaded, and when the service is started and stopped within their application. Detailed instructions are included below.

Cocoapods

Cocoapods is a dependency management system for iOS and OSX projects. It automates the configuration of workspaces and static library projects to manage 3rd party library dependencies in Xcode projects. Detailed instructions on integrating your app with Reveal using Cocoapods are included below.

Important Notes

Static Library Framework Integration

Integrating the static library into your iOS application is the quickest and easiest way to enable Reveal introspection when the application launches.

WARNING: You should not ship a product which has been linked with the Reveal library. The instructions below outline a way to use build configurations to isolate linking the Reveal static library to Debug builds.

  1. Open your iOS project in Xcode.

  2. Launch Reveal and select Help / Show Reveal Library in Finder.

  3. Drag Reveal.framework in to the Frameworks group in the Project Navigator panel of your project.

    Optionally select Copy items into destination group’s folder (if needed).

    In the Add to targets box, select all targets you want to integrate with.

    Click Finish.

  4. In the Xcode Project Navigator, select the project. For each target you wish to be linked with Reveal:

    Select the Build Phases tab and remove Reveal.framework from the Link Binaries With Libraries section.

    Select the Build Settings tab and add the following arguments to the Debug configuration of the Other Linker Flags setting.

    -ObjC -framework Reveal

    Xcode 4 Users: Also add the following frameworks if they are not already linked with the target.

    -framework CFNetwork -framework QuartzCore -framework CoreGraphics

  5. Build and run your application with a scheme set to use the Debug configuration. If you are running the iOS application on device, ensure that it is on the same network as the Reveal Mac application. If everything worked, you should be able to switch to Reveal and see your iOS application in the app selector pull-down. Select your app and verify that you can see a snapshot of the app matching what you see in the simulator (or device).

  6. Run your application again, this time using a scheme set to use the Release configuration. Verify that Reveal cannot connect to your application. If you can still connect, check to make sure Reveal.framework is not listed in the Link Binaries With Libraries section of the Build Phases tab.

No code needs to be added, nor any headers imported for Reveal integration. The library will load automatically at launch and start the necessary Reveal services within your app. If you need more advanced control of the integration you should look at the Dynamic Library Integration instructions below.

Dynamic Library Integration

Dynamic loading is a good option for developers who want full control over when the library is loaded in to their iOS application. Using the dynamic loading approach, Reveal’s code is not loaded into the application until it is needed at runtime. The library can also be unloaded, if required.

For the curious: iOS supports dynamic library loading just fine, however dynamic libraries must be properly code signed when running on a device outside of the debugger.

WARNING: You should not ship a release product containing the Reveal dynamic library. Apple does not allow dynamic library loading in App Store distributed iOS apps, and will likely reject your app if it contains a dynamic library.

  1. Open your iOS project in Xcode.

  2. Launch Reveal and select Help / Show Reveal Library in Finder.

  3. Drag a copy of libReveal.dylib in to the Frameworks group in the Project Navigator panel of your project.

    Optionally select Copy items into destination group’s folder (if needed).

    In the Add to targets box, DESELECT all targets. This ensures that Xcode doesn’t link the dylib at compile time.

    Click Finish.

  4. In the Xcode Project Navigator, select the project. For each relevant Target select the Build Phases tab and:

    In the Copy Bundle Resources section, add libReveal.dylib. This packages the dylib file in the the app bundle.

    Verify that libReveal.dylib is NOT listed in the Link Binaries With Libraries section. If it is, remove it. The dylib should not be linked at compile time.

    Add the following system frameworks in the Link Binaries With Libraries section if not already present:

    • CFNetwork.framework
    • QuartzCore.framework
    • CoreGraphics.framework - usually included by default by Xcode.
  5. The method below shows how to dynamically load the library at runtime. Add this method to a class of your choice (e.g. your AppDelegate), and modify as you see fit.

    #pragma mark - Reveal
    
    #import <dlfcn.h>
    - (void)loadReveal
    {
        NSString *revealLibName = @"libReveal";
        NSString *revealLibExtension = @"dylib";
        NSString *dyLibPath = [[NSBundle mainBundle] pathForResource:revealLibName ofType:revealLibExtension];
        NSLog(@"Loading dynamic library: %@", dyLibPath);
    
        void *revealLib = NULL;
        revealLib = dlopen([dyLibPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);
    
        if (revealLib == NULL) 
        {
            char *error = dlerror();
            NSLog(@"dlopen error: %s", error);
            NSString *message = [NSString stringWithFormat:@"%@.%@ failed to load with error: %s", revealLibName, revealLibExtension, error];
            [[[UIAlertView alloc] initWithTitle:@"Reveal library could not be loaded" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        }
    }
    

    The Reveal service starts automatically when the NSApplicationDidFinishLaunching notification is posted. A simple integration might call the above method from the AppDelegate’s application:didFinishLaunchingWithOptions: method to ensure the library is loaded before the notification is posted.

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // 
        // Window creation and setup...
        //
    
        [self loadReveal];
    
        return YES;
    }
    

    If you load the Reveal dylib after the NSApplicationDidFinishLaunching notification has been posted, you have to start it manually by posting an IBARevealRequestStart notification.

    - (void)startReveal
    {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:self];
    }
    

    In this scenario you might start the service as the result of tapping a button in a debug menu within your application.

    Notifications for broad control of the service include:

    • IBARevealRequestStart - post this notification to signal the Reveal library to start the service
    • IBARevealRequestStop - post this notification to signal the Reveal library to stop the service

    You can also unload the Reveal library using dlclose(), passing it the handle returned by dlopen(). You should stop the service first by posting the IBARevealRequestStop notification.

    For example, if the result of dlopen() was stored in ivar _revealLib, your stop Reveal method could look like:

    - (void)stopReveal 
    {
        if (_revealLib) 
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStop" object:self];
            if (dlclose(_revealLib) == 0) 
            {
                NSLog(@"Reveal library unloaded");
                _revealLib = NULL;
            }
            else 
            {
                char *error = dlerror();
                NSLog(@"Reveal library could not be unloaded: %s", error);
            }
        }
    }
    

    RUNNING ON DEVICE: To dynamically load the library in an application running on a device outside of the debugger, you need to code sign libReveal.dylib as part of the build process. Go to your Target’s Build Phases tab and select Editor / Add Build Phase / Add Run Script from the main menu. Edit the Run Script to contain:

        set -e
        if [ -n "${CODE_SIGN_IDENTITY}" ]; then
            codesign -fs "${CODE_SIGN_IDENTITY}" "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/libReveal.dylib"
        fi
    
  6. Build and run your application. If you are running the iOS application on device, ensure that it is on the same network as the Reveal Mac application. If everything worked, the Reveal service should start when the code you added is executed. You should be able to switch to Reveal and see your iOS application in the app selector pull-down. Select your app and verify that you can see a snapshot of the app matching what you see in the simulator (or device).

Cocoapods Integration

The Cocoapods specifications repository includes a Podspec for integrating Reveal with your Xcode project. Just add the following to your Podfile.

    pod 'Reveal-iOS-SDK'

Then run pod install in your project directory.

WARNING: Cocoapods does not currently let you limit which libraries are linked to your app using build configurations. Using the approach above you’ll need to remember to remove the Reveal SDK from your Podfile before doing an App Store release build. Another approach is to specify the target against which the Reveal library should be linked (see below) and maintain two separate targets, one for release builds and the other for debug builds. Using this approach means you need to maintain the compile sources and assets for both targets independently.

    target :MyDebugTarget do
      pod 'Reveal-iOS-SDK'
    end

We endevour to keep the Cocoapod repository up to date but at times the Cocoapods Podspec git repository may lag slightly behind released versions of Reveal.