Reveal调试UI利器

作者: fakepinge | 来源:发表于2016-07-01 09:26 被阅读588次

    Reveal

    Reveal是分析、调试iOS应用UI的利器。

    Reveal能够在运行时调试和修改iOS应用程序。它能连接到应用程序,并允许开发者编辑各种用户界面参数,这反过来会立即反应在程序的UI上。就像用FireBug调试HTML页面一样,在不需要重写代码、重新构建和重新部署应用程序的情况下就能够调试和修改iOS用户界面。

    安装Reveal

    Reveal 下载地址:http://revealapp.com/download/

    集成指南

    集成Reveal无需添加任何代码,无需引入任何头文件。库将会在应用启动时自动加载,并在您的应用内部启动必要的Reveal服务。

    三种集成方式

    静态连接

    将Reveal的静态库文件连接入应用,是最简单快捷地启用Reveal检视的方式。

    警告: 不要将Reveal库文件随着正式应用一起发布。 下面的步骤将会展示如何通过构建配置,而把Reveal静态库文件,仅连接到调试构建的流程中。

    1. 在Xcode中打开您的iOS工程。

    2. 启动Reveal并选择Help → Show Reveal Library in Finder,这将会打开Finder窗口,并显示一个名为iOS-Libraries的文件夹。

    3. Reveal.framework 文件拖入Xcode中的Project Navigator面板。

    4. 在下图所显示的Add to targets对话框中,选择所有您希望与Reveal集成的target。可选步骤:选中Copy items if needed,将会把 Reveal.framework 拷贝到工程中——如果您这么做了, 请记住,当更新Reveal至新版本时,也依照上述步骤再次更新此库文件。

    5. 点击Finish。

    6. 选择Build Settings标签,在Other Linker Flags的Debug配置项中加入如下配置。

       -ObjC -lz -framework Reveal
      
    7. 在Xcode中,构建并运行您的应用。如果应用运行于真实设备之上,请确保此设备与正在运行Reveal的Mac机器,处于同一Wi-Fi网络中。

      如果一切正常运行,请切换到Reveal应用,此时您的应用应会出现在应用选择器的下拉列表当中。选中您的应用,确认可以看到此时正在模拟器(或设备)中运行的应用界面截图。

    动态加载

    动态加载允许iOS应用在运行时,可以按需地加载第三方库。采用这种方式,库文件无需连接入应用的可执行文件,而是被加入到了应用Bundle中去,从而在运行时能按需加载。这种方式使得开发者可以在个人应用中,完全自由地控制Reveal库的加载,以及其服务的启动与停止。

    将Reveal加入您的Xcode工程,使得您团队中的其他成员无需任何额外的配置,就可以使用Reveal。

    警告: 永远不要将包含Reveal动态库文件的应用正式发布。Apple不允许将含有动态加载库文件的iOS应用发布到Apple商店中。

    1. 在Xcode中打开您的iOS工程。

    2. 启动Reveal并选择Help → Show Reveal Library in Finder,这将会打开Finder窗口,并显示一个名为iOS-Libraries的文件夹。

    3. libReveal.dylib 文件拖入Xcode中的Project Navigator面板。

    4. 在下图所显示的Add to targets对话框中,反选所有的target。这确保了Xcode不会在编译时连接动态库文件。可选步骤:选中Copy items if needed,将会把 libReveal.dylib 拷贝到工程中——如果您这么做了, 请记住,当更新Reveal至新版本时,也依照上述步骤再次更新此库文件。

    5. 点击Finish。

      进入target的Build Phases标签页,选择Editor → Add Build Phase → Add Run Script菜单。在Run Script阶段中加入以下内容:

      set -e
      
       if [ -n "${CODE_SIGN_IDENTITY}" ]; then
           codesign -fs "${CODE_SIGN_IDENTITY}" "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/libReveal.dylib"
       fi
      
    6. 将下面的代码加入到项目中合适的类文件中(例如您的UIApplicationDelegate),适当修改使之满足您的需要:

      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:

      #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];
               }
           }
       }
      

      警告: 不要在发布(release)构建中调用此方法,确保仅是在应用的调试(debug)构建中加载libReveal.dylib。

    7. 一个简单的集成方式是,在-[UIApplicationDelegate applicationDidBecomeActive:]方法中调用上面声明的- (void)loadReveal方法,以确保Reveal库尽早地被加载进来。
      Swift:

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

      Objective-C:

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

      提示: 在-[UIApplicationDelegate applicationDidBecomeActive:]方法返回之前加载库的一个好处是,将会让Reveal服务在应用启动的同时也自动启动。

      如果您不希望如上述步骤自动启动Reveal服务,也可以以手动的方式来启动,例如通过一个Debug按钮。在应用启动后,自己调用loadReveal方法,然后再分发一个名为IBARevealRequestStart的NSNotification:
      Swift:

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

      Objective-C:

      - (void)startReveal
      {
          [[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
      }
      
    8. 在Xcode中,构建并运行您的应用。如果一切正常运行,请切换到Reveal应用,此时您的应用应会出现在应用选择器的下拉列表当中。选中您的应用,确认可以看到此时正在模拟器(或设备)中运行的应用界面截图。

    CocoaPods

    CocoaPods 是一款针对iOS与OSX项目的依赖管理系统。它大大简化了以往Xcode工程里,对第三方库的依赖管理与配置工作。

    CocoaPods提供了Podspec用于将Reveal集成入您的项目。

    警告: 不要将连接了Reveal库文件的应用用于正式发布。下面的指南描述了一种使用构建配置来使Reveal静态库文件仅在调试构建中连接的方式。

    此说明要求您在之前已经在项目中配置好了CocoaPods,若不然,请先行配置Cocoapods。

    1. 将下面内容加入你的Podfile中:

      pod 'Reveal-iOS-SDK', :configurations => ['Debug']
      
    2. 在项目的根目录下执行 pod install 命令(如果之前已经在项目中使用了Cocoapods,请执行 pod update 命令)。

    从您的Xcode项目中移除Reveal

    根据您实际所选择的Reveal集成方式,请根据下述相关步骤来移除Reveal。

    一旦库文件成功的移除后,下面的内容将不再会在您的应用启动时出现在Xcode控制台:

    INFO: Reveal Server started (Protocol Version X).

    静态连接

    1. 打开您的Xcode工程。
    2. Project Navigator删除 Reveal.framework 的引用。
    3. 在Xcode的 Project Navigator中选中您的工程,对于每一个集成了Reveal得target,请选择 Build Settings 标签页,将下面内容从 Debug 配置中的 Other Linked Flags 设置中移除:
      • -framework Reveal
      • -ObjC and -lz (删除前请确认此配置内容仅是用于Reveal)。
    4. 搞定 - 运行应用,确认Reveal没有和应用连接上。

    动态连接

    1. 打开您的Xcode工程。
    2. 从 Project Navigator 中删除 libReveal.dylib 的引用。
    3. 在Xcode的 Project Navigator中选中您的工程,对于每一个集成了Reveal得target,选择 Build Phases 标签页,如果下列库文件仅供Reveal使用的话,请将它们从 Link Binary With Libraries 配置中移除:
      • libz.dylib
      • CFNetwork.framework
      • QuartzCore.framework
      • CoreGraphics.framework
    4. 将自定义的codesign内容从 Build Phases 下的 Run Script 中删除。
    5. loadReveal / startReveal 方法从您的代码中删除。
    6. 搞定 - 运行应用,确认Reveal没有和应用连接上。

    CocoaPods

    1. 在您的Podfile文件中删除下面这行内容:

      pod 'Reveal-iOS-SDK', :configurations => ['Debug']
      
    2. 在项目的根目录下执行 pod update 命令。

    3. 如果您的 Podfile 中只有 Reveal-iOS-SDK 一个pod依赖,请根据此说明,将CocoaPods从项目中完全移除。

    4. 搞定 - 运行应用,确认Reveal没有和应用连接上。

    显示效果

    上图是Reveal的运行界面,其界面主要分成3部分:

    • 左边部分是整个界面的层级关系,在这里可以以树形级层的方式来查看整个界面元素。

    • 中间部分是一个可视化的查看区域,用户可以在这里切换2D或3D的查看方式,这里看到的也是程序运行的实时界面。

    • 右边部边是控件的详细参数查看区域,当我们选中某一个具体的控件时,右边就可以显示出该控件的具体的参数列表。我们除了可以查看这些参数值是否正确外,还可以尝试修改这些值。所有的修改都可以实时反应到中间的实时预览区域。

    重要提示

    1. 不要将连接了Reveal库文件的应用正式发布。 Reveal的检视机制,会将您应用的许多内部信息暴露出来,而这将很可能导致您的应用被Apple审查团队拒绝发布。Reveal的目的仅用于内部开发与应用调试。
    2. 当iOS应用进入后台后,Reveal服务将会自动停止。 当应用重新打开时,它又会自动启动。
    3. Reveal支持基于iOS 7及更新版本而编译的应用。 构建配置中的iOS Deployment Target也必须是'iOS 7.0'或更新版本。 如果iOS版本太旧,您有可能会在构建应用过程中遇到连接错误。
    4. Reveal使用Bonjour协议来连接运行时的iOS应用。 如果您的iOS应用是运行在真实的设备之上,那么此设备也需要处在同一个网络之内,以便电脑上的Reveal应用能够与之连接。如果您在连接应用时仍遇到问题,请先检查防火墙和代理设置,以确保它们没有阻碍通讯。

    相关文章

      网友评论

        本文标题:Reveal调试UI利器

        本文链接:https://www.haomeiwen.com/subject/pjpfjttx.html