使用Reveal调试和分析UI

在移动开发当中,APP的界面的编写和调试占了相当的一部分时间,那么在不借助Xcode之外的第三方工具的情况下来调试UI是一件相对来说比较耗费时间的工作,一般情况下,你除了使用Xcode的自带的UI调试器之外,只能使用输出View结构的方式来调试UI的问题。这个在节奏紧凑的开发过程当中是非常不爽的一件事。专业的事情应该交给专业的工具来做,对于调试UI的这件事情来说,应该交给Reveal这个工具。

Reveal是一个程序界面调试工具,可以调试iOS apps和tvOS apps。使用Reveal,我们可以在开发时动态地查看和修改应用程序的界面。避免每次修改UI的时候都要重新运行程序。接下来按照规矩,如下图,能用图说明清楚的就不用文字来表达了,文字的表现力不够直观。


Reveal程序运行截图

1、如“Reveal程序运行截图”所示,我使用的Reveal官方提供的项目来作为调试Demo,最左边的是Demo的在模拟器的运行效果,右边的App就是Reveal,我第一眼看到这个Reveal有种惊艳的感觉。App的左上方是我此刻调试的模拟器,左下方是我此刻查看UI细节信息的UIView,App的中间部分就是此刻正在分析的设备界面,App的最右边是不是看着和Xcode的Xib编辑器有点类似,没错这个就是可以动态查看和修改UI的地方。这个修改的方式和Xcode的Xib修改Ui细节类似,相信你对这个已经很有感觉了,只要稍加查看就可以上手的。


Reveal查看UI

2、如“Reveal查看UI图”所示,Reveal查看UI的维度也是可以选择的,可以有二维视角,也可以有三维视角。我选择了一个三维视角,如上图所示左边点击展开UIView的层级,点击对应的View查看这个View的对应约束,用这样的方式来查看UI的约束是不是太直观了。

说了这么多,最重要的还没有说出来呢,那就是这个Reveal这么叼,那我要怎么使用它来调试我自己的App界面,或者查看其他知名App的UI布局实现信息。接下来还是先说说怎么用它来调试我们自己的App界面。


使用Reveal来调试模拟器中的我们的App的界面是最简单的。只需要添加对应的断点即可。


1、在Xcode项目中,选择“View → Navigators → Show Breakpoint Navigator”。


Add Symbolic Breakpoint”

2、在左边底部面板,点击"+"号按钮,然后选择“Add Symbolic Breakpoint”。

3、在Symbol字段里面填入“UIApplicationMain”。

4、点击“Add Action”按钮,并确认一下“Action”是设置到“Debugger Command”。

5、在Action下的文本框中贴入如下表达式

expr (Class)NSClassFromString(@"IBARevealLoader") == nil ? (void *)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2) : ((void*)0)


检查选项

6、检查选项“Automatically continue after evaluating actions”是否勾选了。



Move Breakpoint To → User

7、右键点击新建的断点,然后选择“

Move Breakpoint To → User

”保存给所有的项目使用。


打开Reveal

8、编译,在模拟器上运行你的程序,然后打开Reveal,查看你的布局。



使用真机调试我们的App界面,如果你的真机是没有越狱的设备,那么使用Reveal来调试UI的步骤是最麻烦的。


打开Reveal的库位置
Reveal的库
拖库进项目

1、如“拖库进项目”图所示,把Reveal的库拖到我们项目中来。



选择添加的方法

2、如“选择添加的方法”所示,不要把库加到我们App的target里面。



添加到Bundle Resource

3、如“添加到Bundle Resource”图所示,将Reveal的库添加到Bundle Resource。



选择添加到Bundle Resource

4、如“选择添加到Bundle Resource”所示,选择对应的Reveal的库到Bundle Resource。



添加Reveal库成功

5、如“添加Reveal库成功”图所示,当Bundle Resources出现了Reveal库的时候就添加成功了。



添加对应的系统库

6、如“添加对应的系统库”所示,添加Reveal运行时所需要的系统库。



添加Reveal运行脚本

7、如“添加Reveal运行脚本”所示,接下来是添加Reveal的运行脚本,是不是感觉到麻烦了,如果你有更好调试非越狱真机的方法欢迎告知我,谢谢!



写入Reveal对应的脚本

8、如“写入Reveal对应的脚本”所示,写入Reveal运行时候需要的脚本,脚本内容如下:

set -e

if [ -n "${CODE_SIGN_IDENTITY}" ]; then

codesign -fs "${CODE_SIGN_IDENTITY}" "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/libReveal.dylib"

fi




加载方法


在生命周期方法里面调用加载方法

 9、如“加载方法”图所示,需要在AppDelegate里面写对应的Reveal加载方法,我使用的是Swift版本的,当然也有OC版本的。然后如“在生命周期方法里面调用加载方法”图所示,需要在生命周期方法里面调用Reveal的加载方法。各个版本加载方法现提供如下(需要注意的是不要在发布版本去加载Reveal,因为它仅适合调试):

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 <dlfcn.h>

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

}

}

}



成功运行结果

10、保证你的电脑和你的真机在同一个网段内,然后运行你的App,在Reveal中选择你的设备,稍等片刻,你的Reveal就会出现对应的UI界面了,如“成功运行结果”界面所示(我的运行设备是iPad)。使用Cmd+R快捷键可以刷新你的Reveal界面。


福利福利福利!!!越狱设备福利!!!

非越狱真机调试是最麻烦的,以前真机还可以使用断点来调试的,现在都不能用了。不再纠结这个了,如果你的设备是越狱设备,那么恭喜你,你要使用Reveal简直是轻松加esay。点开链接一键配置,用Reveal Loader配合Reveal调试App会有惊喜。这个是Richard Heard这位开发者开发的一个Reveal插件,你只需要安装这个插件,保证你的电脑和你的真机在同一个网段内,然后选择你想要调试的任何App(对,没错,不是你自己家的App也可以搞,只有你想不到,没有你看不到的,哈哈哈,巨大福利)。

感谢你看完了本文,因为我感觉自己写的文字加上图片内容很多了,哈哈!这篇文章是来源于我自己的工作实践经验,在接触和使用使用Reveal之前,我一直都是使用打印View结构的方式来调试UI,但是这个方法的输出很不友好,因为没有没有接触到特别好用的工具,所以也不觉得这个打印的方法有多耗费时间。但是现在我不这么想了,根据我的经验判断,但凡不能马上看出问题的UI布局,我都会马上使用Reveal,因为省时省力,而且它也挺有意思的。

看完我的博客,如果你觉得我写的文章对你有一丁点儿帮助的话,那么请你在下面点个赞,让我知道这文章有起了它应该起的作用,谢谢!!!

参考资料:

Reveal的项目:https://github.com/revealapp/Revert

Reveal Loader安装使用 :http://bbs.iosre.com/t/reveal-loader-reveal-app/187

不修改Xcode工程来使用Reveal:  http://support.revealapp.com/kb/getting-started/integrating-reveal-load-reveal-without-changing-your-xcode-project

Xcode配置Reveal:http://support.revealapp.com/kb/getting-started/integrating-reveal-add-reveal-to-your-xcode-project

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容