« Integrating Reveal / Dynamic Loading

Add Reveal to your Xcode Project

Adding Reveal to your Xcode project allows all members of your team to use Reveal without having to perform further configuration.

WARNING: Never ship a release build of your app containing the Reveal dynamic library. Apple does not allow dynamic library loading in iOS and tvOS apps distributed via the App Store.

  1. Open your iOS or tvOS project in Xcode.

  2. Launch Reveal and select either "iOS Library" or "tvOS Library" from the Help → Show Reveal Library in Finder menu. This will open a Finder window with the appropriate framework selected.

    Show Reveal Library in Finder

  3. Drag libReveal.dylib (or libReveal-tvOS.dylib for tvOS apps) in to the Project Navigator panel of your project in Xcode.

    Drag Reveal dylib to project

  4. In the add to targets dialog that is shown, deselect all targets. This ensures that Xcode doesn't link the dynamic library at compile time. Optionally, select Copy items if needed to copy libReveal.dylib (or libReveal-tvOS.dylib for tvOS apps) into your project — if you do, you'll need to remember to update this library whenever Reveal is updated by following the previous steps again.

    Copy resource to project dialog

  5. Click Finish.

  6. In Xcode's Project Navigator, select your project. For each target that you wish to use with Reveal:

    Copy library to bundle resources

    • In the Copy Bundle Resources section, add libReveal.dylib (or libReveal-tvOS.dylib for tvOS apps).

    • Under Link Binary with Libraries:

      • Remove libReveal.dylib and libReveal-tvOS.dylib if either is present - the dylib should not be linked at compile time.
      • Add the following system frameworks and libraries if they're not present:
        • libz.tbd
        • CFNetwork.framework
        • QuartzCore.framework
        • CoreGraphics.framework - this is usually included by default by Xcode.
  7. To dynamically load the library in an application running on a device outside of the debugger, you need to code sign libReveal.dylib (or libReveal-tvOS.dylib for tvOS apps) as part of the build process.

    Add Run Script phase

    Go to your target's Build Phases tab and select Editor → Add Build Phase → Add Run Script menu. Edit the Run Script to contain:

    For iOS targets:

     set -e
    
     if [ -n "${CODE_SIGN_IDENTITY}" ]; then
         codesign -fs "${CODE_SIGN_IDENTITY}" "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/libReveal.dylib"
     fi

    For tvOS targets:

     set -e
    
     if [ -n "${CODE_SIGN_IDENTITY}" ]; then
         codesign -fs "${CODE_SIGN_IDENTITY}" "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/libReveal-tvOS.dylib"
     fi
  8. Add the following code to an appropriate class (e.g. your UIApplicationDelegate) in your project, and modify it to suit your needs:

    Swift:

     // MARK: - Reveal
    
     func loadReveal() {
         if NSClassFromString("IBARevealLoader") == nil {
             let revealLibName = "libReveal" // or "libReveal-tvOS" for tvOS targets
             let revealLibExtension = "dylib"
             var error: String?
    
             if let dylibPath = NSBundle.mainBundle().pathForResource(revealLibName, ofType: revealLibExtension) {
                 print("Loading dynamic library \(dylibPath)")
    
                 let revealLib = dlopen(dylibPath, RTLD_NOW)
                 if revealLib == nil {
                     error = String(UTF8String: dlerror())
                 }
             } else {
                 error = "File not found."
             }
    
             if error != nil {
                 let alert = UIAlertController(title: "Reveal library could not be loaded", 
                                             message: "\(revealLibName).\(revealLibExtension) failed to load with error: \(error!)",
                                      preferredStyle: .Alert)
                 alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
                 UIApplication.sharedApplication().windows.first?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
             }
         }
     }

    Objective-C:

     #import 
    
     #pragma mark - Reveal
    
     - (void)loadReveal
     {
         if (NSClassFromString(@"IBARevealLoader") == nil)
         {
             NSString *revealLibName = @"libReveal"; // or @"libReveal-tvOS" for tvOS targets
             NSString *revealLibExtension = @"dylib";
             NSString *error;
             NSString *dyLibPath = [[NSBundle mainBundle] pathForResource:revealLibName ofType:revealLibExtension];
    
             if (dyLibPath != nil)
             {
                 NSLog(@"Loading dynamic library: %@", dyLibPath);
                 void *revealLib = dlopen([dyLibPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);
    
                 if (revealLib == NULL)
                 {
                     error = [NSString stringWithUTF8String:dlerror()];
                 }
             }
             else
             {
                 error = @"File not found.";
             }
    
             if (error != nil)
             {
                 NSString *message = [NSString stringWithFormat:@"%@.%@ failed to load with error: %@", revealLibName, revealLibExtension, error];
                 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Reveal library could not be loaded" 
                                                                                message:message
                                                                         preferredStyle:UIAlertControllerStyleAlert];
                 [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
                 [[[[[UIApplication sharedApplication] windows] firstObject] rootViewController] presentViewController:alert animated:YES completion:nil];
             }
         }
     }

    WARNING: You should not call this method from a release build. Be sure to only load libReveal.dylib from debug builds of your application.

  9. A simple integration might call the method above from within the -[UIApplicationDelegate applicationDidBecomeActive:] method to ensure the library is loaded as soon as possible:

    Swift:

     func applicationDidBecomeActive:(application: UIApplication) {
         self.loadReveal()
     }

    Objective-C:

     - (void)applicationDidBecomeActive:(UIApplication *)application
     {
         [self loadReveal];
     }

    Note: Loading the library before -[UIApplicationDelegate applicationDidBecomeActive:] returns has the added bonus that the Reveal Service will start automatically at launch.

  10. If you prefer not to have the Reveal Service start automatically as described in the previous step, it can be started manually such as via a Debug button or similar. Just call the loadReveal method yourself after the app has started, and then post an NSNotification named IBARevealRequestStart:

    Swift:

     func startReveal() {
         NSNotificationCenter.defaultCenter().postNotificationName("IBARevealRequestStart", object: nil)
     }

    Objective-C:

     - (void)startReveal
     {
         [[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
     }
  11. In Xcode, build and run your application using a scheme that is set to use the Debug configuration.

    Reveal App Chooser showing Soundstagram

    If everything worked, you should be able to switch to Reveal and see your iOS or tvOS application listed 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.

Getting Help

If you have any problems or questions about integrating Reveal into your app, head over to our support site.