http://blog.csdn.net/jackfrued/article/details/50934092

 
 

Reveal是iOS开发工具中的神器之一,它能够在应用程序运行过程中调试应用程序界面。 通过Reveal我们可以连接到应用程序,并允许开发者编辑各种用户界面参数,结果会马上在用户界面上呈现。就像Web开发人员用浏览器提供的开发人员工具调试页面一样,Reveal允许开发者在不修改代码、不重新构建项目、不重新部署应用程序的情况下就能够调试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配置项中加入如下配置。

    1. -ObjC -lz -framework Reveal
  7. 如果您使用的是Xcode 7, 请确认 Reveal.framework 所在的目录在您的工程配置项 “Framework Search Paths” 中。具体的内容看起来会像这样。

    1. FRAMEWORK_SEARCH_PATHS = $(inherited) "$(SYSTEM_APPS_DIR)/Reveal.app/Contents/SharedSupport/iOS-Libraries"
  8. 在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。

    6. Copy Bundle Resources配置区域中,加入libReveal.dylib

    7. Link Binary With Libraries配置项中:

      • ​如果已有libReveal.dylib,请将其移除——不应在编译时连接dylib文件。
      • 如果下列系统框架与库文件还不存在,请将他们加入: 
        • libz.tdb
        • CFNetwork.framework
        • QuartzCore.framework
        • CoreGraphics.framework - Xcode一般默认会在工程中包含此框架文件。
    8. 为了能在debugger之外,将库文件动态地载入设备上的应用,您需要在构建过程中加入对libReveal.dylib文件的code sign。

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

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

  1. 将下面的代码加入到项目中合适的类文件中(例如您的UIApplicationDelegate),适当修改使之满足您的需要:

    Swift:

    1. // MARK: - Reveal
    2. func loadReveal() {
    3. if NSClassFromString("IBARevealLoader") == nil {
    4. let revealLibName = "libReveal" // or "libReveal-tvOS" for tvOS targets
    5. let revealLibExtension = "dylib"
    6. var error: String?
    7. if let dylibPath = NSBundle.mainBundle().pathForResource(revealLibName, ofType: revealLibExtension) {
    8. print("Loading dynamic library \(dylibPath)")
    9. let revealLib = dlopen(dylibPath, RTLD_NOW)
    10. if revealLib == nil {
    11. error = String(UTF8String: dlerror())
    12. }
    13. } else {
    14. error = "File not found."
    15. }
    16. if error != nil {
    17. let alert = UIAlertController(title: "Reveal library could not be loaded",
    18. message: "\(revealLibName).\(revealLibExtension) failed to load with error: \(error!)",
    19. preferredStyle: .Alert)
    20. alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    21. UIApplication.sharedApplication().windows.first?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
    22. }
    23. }
    24. }
  2. Objective-C:


    1. #pragma mark - Reveal
    2. - (void)loadReveal
    3. {
    4. if (NSClassFromString(@"IBARevealLoader") == nil)
    5. {
    6. NSString *revealLibName = @"libReveal"; // or @"libReveal-tvOS" for tvOS targets
    7. NSString *revealLibExtension = @"dylib";
    8. NSString *error;
    9. NSString *dyLibPath = [[NSBundle mainBundle] pathForResource:revealLibName ofType:revealLibExtension];
    10. if (dyLibPath != nil)
    11. {
    12. NSLog(@"Loading dynamic library: %@", dyLibPath);
    13. void *revealLib = dlopen([dyLibPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);
    14. if (revealLib == NULL)
    15. {
    16. error = [NSString stringWithUTF8String:dlerror()];
    17. }
    18. }
    19. else
    20. {
    21. error = @"File not found.";
    22. }
    23. if (error != nil)
    24. {
    25. NSString *message = [NSString stringWithFormat:@"%@.%@ failed to load with error: %@", revealLibName, revealLibExtension, error];
    26. UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Reveal library could not be loaded"
    27. message:message
    28. preferredStyle:UIAlertControllerStyleAlert];
    29. [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
    30. [[[[[UIApplication sharedApplication] windows] firstObject] rootViewController] presentViewController:alert animated:YES completion:nil];
    31. }
    32. }
    33. }
  3. 警告: 不要在发布(release)构建中调用此方法,确保仅是在应用的调试(debug)构建中加载libReveal.dylib。

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

    1. 1. func applicationDidBecomeActive:(application: UIApplication) {
    2. self.loadReveal()
    3. }
  5. Objective-C:

    1. (void)applicationDidBecomeActive:(UIApplication *)application
    2. {
    3. [self loadReveal];
    4. }
  6. 提示: 在-[UIApplicationDelegate applicationDidBecomeActive:]方法返回之前加载库的一个好处是,将会让Reveal服务在应用启动的同时也自动启动。

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

    1. func startReveal() {
    2. NSNotificationCenter.defaultCenter().postNotificationName("IBARevealRequestStart", object: nil)
    3. }
  7. Objective-C:

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

CocoaPods

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

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

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

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

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

    1. 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文件中删除下面这行内容:

    1. 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调试其它应用界面

如果你的设备越狱了,那么还可以用Reveal来”调试“其它应用界面,什么时候会有这种奇怪的需求呢?——当我们想学习别人是如何实现界面效果的时候。iOS设备的目录/Library/MobileSubstrate/DynamicLibraries 下存放着所有在系统启动时就需要加载的动态链接库,所以我们只需要将Reveal的动态链接库上传到该目录即可。

对于越狱的设备,我们可以在安装OpenSSH之后,用scp来上传该文件。具体步骤如下:

将libReveal.dylib 上传到 /Library/MobileSubstrate/DynamicLibraries 
如果libReveal.dylib没有执行权限,用chmod +x libReveal.dylib命令,给其增加执行权限 
执行 killall SpringBoard 重启桌面

iOS开发笔记 - 界面调试神器Reveal的更多相关文章

  1. iOS开发笔记7:Text、UI交互细节、两个动画效果等

    Text主要总结UILabel.UITextField.UITextView.UIMenuController以及UIWebView/WKWebView相关的一些问题. UI细节主要总结界面交互开发中 ...

  2. iOS开发笔记-两种单例模式的写法

    iOS开发笔记-两种单例模式的写法   单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...

  3. iOS开发笔记--什么时候调用layoutSubviews

    iOS开发笔记--什么时候调用layoutSubviews 分类: iOS2014-04-22 16:15 610人阅读 评论(0) 收藏 举报 今天在写程序时候遇见layoutSubviews触发时 ...

  4. IOS开发笔记(4)数据离线缓存与读取

    IOS开发笔记(4)数据离线缓存与读取 分类: IOS学习2012-12-06 16:30 7082人阅读 评论(0) 收藏 举报 iosiOSIOS 方法一:一般将服务器第一次返回的数据保存在沙盒里 ...

  5. IOS开发笔记 IOS如何访问通讯录

    IOS开发笔记  IOS如何访问通讯录 其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的. 幸好ios6.0 以后给了个权限控制.当打开app的时候你可以选择拒绝. 实现方法: [plain] ...

  6. 【Swift】iOS开发笔记(二)

    前言 这个系列主要是一些开发中遇到的坑记录分享,有助于初学者跨过这些坑,攒够 7 条发一篇. 声明  欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.com 农民伯 ...

  7. 菜鸟手下的iOS开发笔记(swift)

    在阳春4月的一天晨会上,有一个老板和蔼的对他的一个菜鸟手下说:“你既然会Android,那你能不能开发iOS?” 不是说好的要外包的吗?内心跌宕,但是表面淡定的菜鸟手下弱弱的回道:“可以试试”. 第二 ...

  8. iOS开发笔记18:一些编译、开发调试、打包的细节整理

    1.以链库的方式引用第三方库 一些特殊场景可能会要求使用链库的方式使用第三方库,大体设置如下: ①Other Linker Flags里进行设置,格式为-l+库名称 ②Libray Search Pa ...

  9. 七款Debug工具推荐:iOS开发必备的调试利器

    历时数周或数月开发出来了应用或游戏.可为什么体验不流畅?怎么能查出当中的纰漏?这些须要调试诊断工具从旁协助.调试是开发过程中不可缺少的重要一环.本文会列举几个比較有效的调试诊断工具,能够帮助你寻根究底 ...

随机推荐

  1. mysql 查询 45 道题

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  2. Talking about Health

    George: Doctor, what is the best way to stay healthy? Dictor: Having a good diet is probably the mos ...

  3. L10,not for jazz

    expressions: It is called a clavichord这被称为古钢琴 a friend of my father's我父亲的朋友   words: musical,adj,音乐的 ...

  4. PHPer转战Android的学习过程以及Android学习

    原文作者: eoeadmin原文地址: http://my.eoe.cn/shuhai/archive/19684.html-------------------------------------- ...

  5. 设置span的宽度

    设置span的宽度 在默认的情况下,利用css样式对span进行宽度设定是无效,但有时为了某种排版的要求,需要对span进行宽度设定,那么如何在html中利用css样式设定span的宽度? 思路:这看 ...

  6. textbox文本键盘全选

    private void textBox1_KeyDown(object sender, KeyEventArgs e)        {            if (e.Modifiers == ...

  7. OpenGL------三维变换

    我们生活在一个三维的世界——如果要观察一个物体,我们可以:1.从不同的位置去观察它.(视图变换)2.移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它.(模型变换)3.如果把物 ...

  8. kali系统安装

    kali live 安装到U盘 http://www.backtrack.org.cn/thread-17197-1-1.html 用Live U盘安装Kali Linux http://cn.doc ...

  9. (转)mahout中k-means例子的运行

           首先简单说明下,mahout下处理的文件必须是SequenceFile格式的,所以需要把txtfile转换成sequenceFile.SequenceFile是hadoop中的一个类,允 ...

  10. 某技术大牛的帖子(android项目总结)

    1. 一般性控件需要设置onclick事件才会有点击效果(selector). 2.  <item android:drawable=”@drawable/btn_ct_green” /> ...