详解Xcode 7的视图调试_xcode视图-程序员宅基地

技术标签: iOS_UI  

http://www.cocoachina.com/ios/20150423/11658.html

本文由远的风景翻译自raywenderlich,作者:Scott Berrevoets
原文:View Debugging in Xcode 6
app-view (1).jpg
开发者会经常遇到视图或者Auto Layout约束中存在bug的情况,并且这种bug很难通过代码发现,所以开发者很有必要熟知如何进行简单高效的视图调试,而Xcode 6的发布使得视图调试变得前所未有的简单。

开发者不用将frames打印到控制台,然后在脑海中可视化视图的布局,现在你可以在Xcode中查看整个视图层次。

本教程会带你熟悉所有可以操作的不同选项。你做好写代码的准备了吗?这个问题有点令人烦心,因为你根本就不想写代码。你可以在Xcode 6中检查开源库的视图层次,了解它的编写方法---最重要的是不用看任何代码。

开始

本教程使用Jesse Squires 编写的JSQMessagesViewController库,库的UI看起来非常熟悉,类似Messages app。

先在 GitHub project page下载源码并解压。

注意: 该库使用了CocoaPods来管理和其他库之间的依赖关系,不熟悉的话可以先看看CocoaPods tutorial

接着在终端找到解压项目,运行 pod install 安装所需依赖关系。打开JSQMessages.xcworkspace并编译,然后在iPhone5s模拟器中运行应用程序。  (可使用任意尺寸的模拟器,本教程中使用的是4英寸的模拟器,你可以选择4英寸模拟器以便于快速了解教程内容)

注意: Live View Debugging仅支持在iOS 8上运行应用程序,不支持iOS 7,即便你用的是Xcode 6。 

点击项目中的 Push via storyboard选项 进入与Steve Jobs 和Tim Cook消息发送界面线程,这就是你将要查看的视图。

Screen-Shot-2015-04-07-at-12.03.28-PM-280x500.png

Even Steve Wozniak joins the fun!

回到Xcode并点击调试栏中的Debug View Hierarchy按钮 ,或者通过Debug\View Debugging\Capture View Hierarchy操作,效果是一样的。

404.png

Xcode会打断app的运行并进行调试,该操作和你使用调试栏上的的"pause"按钮暂停app运行一样。此外,Xcode会展示canvas(译者注:以下简称"画布")而不是代码编辑器。Xcode在canvas上绘制了app主窗口的整个视图层次,包括指示每个视图边界的细线(称之为线框图)。

21.png

如果往视图层次上添加一个子视图,也就是在当前的视图堆栈上添加layer。由于大部分views不会叠加,所以运行app时,所有的views看起来像是大layer的一部分,下图非常接近这种描述,不过带着一些额外的线。

现在你所看到的是一个可视化的视图堆栈。在canvas中点击并拖动,会看到视图层次的3D模型。

22.gif

你可以从上、下、左、右多个角度查看视图层次。

745.png

注意:在尝试的过程中,canvas可能不会像教程中展示的这样。为确保你是在同一个页面,请按下cmd + 6 调出Debug navigator。

在面板底部左侧有两个按钮。如下图所示,取消对这两个按钮的选定,否则会隐藏一些视图。

23.png

探索视图层次(Exploring the View Hierarchy)

最自然最常用的方式是从左边开始探究3D模型,稍后教程为解释为什么要这么做。向左拉动视图层次,如下图所示:

24.png

如果你想可视化app的构建,那么从多个角度查看视图层次就非常有用了。不过,在堆栈的底部(左边)有很多空视图,它们是什么呢?

点击最左边的视图(也就是最后边的视图),Xcode会对其进行高亮。画布上方的Jump Bar(跳转栏)更新展示一个UIWindow作为最新项目--最新项目通常指出了当前选中的项目以及其class类型。

77.png

由于该app只使用一个窗口,所以可假定位于跳转栏前边的UIWindow 是app的主要窗口,也就是AppDelegate的 window 属性。

不过,似乎检查这个图层并没有多大意义。那下一个视图呢?在画布中,点击窗口最右边的视图(也就是最上边的视图),再看看跳转栏(Jump Bar)看看有什么不一样的。UILayoutContainerView,甚至不是一个公开类。

75.png

这时候,视图层次看起来是这样的:

1.UINavigationTransitionView:导航控制器在这里发生转场行为的容器视图。

2.UIViewControllerWrapperView: 包含view controller 的view属性的封装视图。

3.UIView: view controller的最上层视图 (与view controller的view 属性一致)

4.JSQMessagesCollectionView: 工程使用collection view来展示所有消息。

Focusing on Views of Interest(关注与调试相关的视图)

在调试该特定视图层次时,头四个视图(从窗口开始)实际上是视觉"噪音",它们并无多大意义,会让你分心,如果能过滤掉这些"噪音"视图就最好不过了。

你当然可以这么做!在画布的右下角有一个双滑块儿滑杆,左右滑动滑块可帮你暂时隐藏一些视图,默认情况下,滑块在滑杆的左右两端。

79.png

将滑块左端滑块向右滑动一点,画布中app的线框图会一层层消失。将滑块儿拖得更远一点,UINavigationTransitionView也消失不见了。

根据需要将左端滑块儿尽可能拖得远一些,从而隐藏JSQMessagesCollectionView的父视图。你的画布看起来应该和下边类似:

80.png

在右侧,你会发现导航栏似乎有点让人分心,但是它的的确确位于collection view的最上层,不方便查看下层布局。幸运的是你可以隐藏它。

由于你主要关于屏幕上较小的一个区域,并且导航栏上还有很多比导航栏更小的元素。这时候放大导航栏可以让你更清楚地看到界面是如何布局的。

使用缩放控件按钮,它是一组三个的按钮,居中展示在画布中。

10.png

这一组按钮有放大"+"、缩小"-"以及将视图重置到正常的水平的"="三种选择,

11.png

注意:如果你使用的是触控板,两指捏合和缩放也能缩小和放大视图。如果你一次性缩放过多,那么屏幕上的内容就不能完全展示,这时候使用触控板还是比较有用的。当然你也可以使用鼠标滑轮进行缩放。

虽然通过缩放toolbar获得额外的细节非常不错,但这些视图仍紧紧地叠加在一起,要分清谁是谁并不容易。

想要解决这个问题,可以使用画布左下角的spacing slider,向右拖动圆形滑块儿越远,不同同视图之间的间距。视图间的间距会随着滑块儿拖动的距离增加而变大。

13.png

在该案例中,尽可能地向右移动滑杆儿,以避免工具栏中视图叠加。你可以试试在画布上拖放视图以达到理想的效果。

14.png

画布右下角隐藏视图的滑杆,将右端滑块儿移至左端,直到剩下UINavigationBar。选择最上边的图层,你可以使用Jump Bar来辨认每个视图的类。首先你会看到导航项目消失了,接着是包含它们的按钮,然后是一些私有视图,最后是导航栏。

15.png

啊?没有导航栏了!

注意:旋转画布查看3D视图层次,如果最顶层视图位于左侧,那么滑杆儿的左侧滑块儿依旧从堆栈底部移除视图,现在是在右侧。同样,不管顶层视图在左侧还是右侧,右侧滑块儿都从堆栈的顶部开始移除。

将滑块儿从左侧移至右侧,视图从右向左逐渐消失(反之亦然),这是有违直觉的,这也是让顶层视图位居右侧,这种查看3D模型的方式才是最自然的方式,就是我们在教程最初提到的那一点。

不幸的是,隐藏导航栏(包含_UIBackdropView根视图)视图也会让屏幕底部toolbar里的内容消失。调整缩放度或向下移动画布才能看到发生的变化。

由于toolbar项目是屏幕上重要的一部分,你需要查看这些内容,所以仅仅隐藏视图直到(但不包括)剩下_UIBackdropView,导航栏堆栈看起来像是下边这种:

16.png

More View Options(更多视图选项)

现在已经隐藏了不相关的视图,我们接着要从正面再看这个屏幕。你可以将3D模型拖回原位,不过有时候很难刚刚好,还好我们有其他办法。

在3D模型的下方---缩放按钮的左侧有一组四个按钮,从左向右数第三个按钮是ResetViewing Area按钮,它可以取消旋转并从正面展示视图层次,像在模拟器或者设备上一样。

17.png

画布看起来应该和下边的一样:

18.png

你可能注意到你在调试器中所见到的,并不全是app实际运行时的样子。

首先,单个视图周围易燃有线框图包围,它们可以让你查看透视图或者没有任何内容的视图,不过如果你不需要细节信息,线框图就会让事情变得杂乱。

你可以使用View Mode按钮进行选择-在Reset Viewing Area按钮的右侧。点击视图模式按钮,你可以选择只查看线框图、只查看内容或者同时查看两者。

19.gif

如果你主要是对位置感兴趣,并且不大关心视图看起来什么样子,那么线框图是非常有用的。当你想要调试视图的外观时,仅展示视图内容就非常有用了。

想要减少线框图引起的杂乱(尤其是靠近导航栏和toolbar的地方),可将查看模式更改为Contents ,以移除所有线框图,仅留下app的核心部分。

747.png

接下来,是从当前视图中忽略的几点。

当你运行app时,你将会看到文本气泡上的标签,指示信息发送者名称或者信息的时间戳,以及最后一个气泡中Golden Gate Bridge的图片。但是调试器并不会展示这些标签和图片。想要解决这个问题,可查看画布上中间一组按钮的第一个,可展示或者隐藏省略掉的视图。这些视图的clipsToBounds属性设置为了YES。

78.png

这是标签相关的,大概由于较长的名字和日期不应当延伸到标签的界限之外。这一点同样应用于图片,图片使用圆角半径并剪切以生成圆角图片。点击该按钮,你会注意到这些视图将不再出现在Xcode中。

79.png

注意:你可能注意到可视项目周围仍有线框图,如果是这种情况,使用你先前使用的View Mode按钮

打开和关闭线框图,问题即可解决。

你已经都了解了:在Xcode中近乎完美地复制了视图层次。

802.png

So easy!

Inspecting Views(查看视图)

已经了解了最重要的部分,现在看看这些不同视图的布局。

你已经知道了collection view如何让这些视图聚集在一起,但是如果能看到这些不同元素的整体结构就更好了。当然可以啦!

按下cmd + 6 调出Debug navigator,和其他调试会话一样,Debug navigator提供了当前会话的文本信息。对于视图调试来说,这意味着Xcode提供了所有窗口中视图的视图树。展开Debug navigator的视图树后是这个样子的:

76.png

注意:在Debug navigator的底部,你会看到一个选项可以控制在视图树中展示哪种类型的项目。苹果的文档表示左边的按钮将系统视图实现的私有元素过滤出来,不过这个按钮在Xcode 6.2中似乎不起作用。

右边按钮可隐藏那些将其 hidden 属性设置为YES的视图,并且搜索栏仅展示匹配搜索条件的视图和约束。

出于本教程的目的,取消对这两个按钮的选择,并且不使用任何搜索过滤。

这是个不错的而开始。展开最后一个JSQMessagesCollectionViewCellOutgoing,它只有一个子视图UIView。如果你以前使用过collection view,那你应该知道这个是讲得通的,因为任何UICollectionViewCell都有一个包含cell内容的contentView 属性。

点击但不要展开-将鼠标放在Debug navigator的UIView 上,你会看到Xcode已经在画布上对其高亮,这样你就准确知道它在屏幕的什么地方。

73.png

想要真正了解iOS如何放置该cell,可使用cmd + option + 4打开Size Inspector,该导航器的顶部形象化了视图的边界、位置以及锚点。

72.png

不过,真正有趣的部分是应用于该视图的Auto Layout约束列表。你可以立刻将cell的内容视图的宽和高分别设定为312 point和170 point,并将其居中。封闭的cell同样是312*170 point,所以内容视图占据了整个cell。下边用灰色显示的约束表示它们是指出视图和其子视图之间关系的约束。

想了解一个特定约束的更多细节,首先要展开视图树中的视图,然后展开Constraints项目。你将会看到和Size navigator中一样的约束列表。

722.png

点击第一个约束(self.midX的约束),并通过cmd + option + 3切换至Object inspector。你会看到一个约束概览。编辑约束时,这一点非常类似于Interface Builder。

721.png

除了尺寸和约束信息,你还会看到Object Inspector中特定视图的其他信息。回到Debug navigator,展开视图树中的UIView ,你会到它有3个JSQMessageLabel和两个UIView。选中第一个JSQMessageLabel(带有时间戳的那个),并打开Object Inspector。

029.png

第一个部分展示了对象的类名称和内存地址,第二部分展示了对象的多个公有属性的值。

从图中看出,标签文本的颜色是无alpha 的0.67灰,字体大小是12pt。

针对它们如何被可视化,其他类也有一些有用的信息。回到Debug navigator,展开cell的根UIView 中的第二个UIView,你会看到一个UIImageView。

710.png

从视图树中选择image view,并查看Object inspector。

030.png

你正查看的是展示用户头像的视图-在该例子中是作者的首字母JSQ,你会看到常规图片、便利的贴有标签的图片、较暗的图片以及被标记的高亮,这些将在用户点击cell时展示。

在cell的根视图中,JSQMessageLabel的其他两个实例当前还没有文本,但它们被用于即将进来的消息发送者的名字和消息发送失败时的错误信息。

怎么样,在Xcode中调试视图非常简单吧,继续运行该app,点击Debug bar上的"Continue"按钮,或者执行Debug\Continue,就像你在常规调试中那样。

Live Modifications(实时调整)

现在你已经了解了使用Xcode 6进行视图调试的基础支持,接下来将你所学应用到一个小小的实验中:只使用调试器,确保你在本教程中使用的collection view的垂直滚动指示器为red。

你可以从以下两点开始:

1.由于视图调试和其他调试部分非常像,你可以在终端使用expr 和其他命令,但是需要重新运行项目才能看出所做的变化。更多关于这些命令的信息,请查看debugging apps in Xcode教程

2.由于Objective-C中的指针仅仅是内存地址,所以当你发送对象时,你仅仅发送了一个内存地址。这同样适合于调试器,所以类似po 0x123456abcdef这样的命令会打印出内存地址中的对象描述。

多做几次尝试,如果出现问题,可尝试以下解决方案:

首先要确保将视图模式设置为"Contents"

031.png

在Debug navigator中,展开collection view的视图树,以便清楚知道视图的子视图。

032.png

collection view的最后视图是两个UIImageView实例,是水平方向和垂直方向上的滚动指示器。点击第二个,你会看到水平方向上的指示器在画布中被高亮。

033.png

从Object inspector中复制图片视图的内存地址。

034.png

在这个例子中,滚动指示器的内存地址是0x7fde6c484640。需要做的是给该地址中的对象发送一个setBackgroundColor:信息可将滚动指示器着色。可使用以下代码:

1
expr (void)[0x7fde6c484640 setBackgroundColor:[UIColor redColor]]

继续运行该应用程序,在滚动collection view时,滚动指示器变成了红色。

祝贺你,你已经了解了使用Xcode 6进行视图调试的基本内容。

Old School Debugging(保守调试)

实时调试让使用Xcode 6进行视图调试变得非常简单,但并不意味你之前常用的调试方法已经没有用武之地了。事实上,除了视图调试外,iOS 8引入了一个非常受欢迎的技巧: _printHierarchy.

注意:你已经了解了Xcode 6视图调试的基本内容,所以如果你不喜欢可以直接跳过这个章节。不过如果你非常痴迷一些便捷的旧的技术,那不要错过这个。

打印View Controller Hierarchy

_printHierarchy是 UIViewController 的一个私有方法,你可以用它将view controller 层次打印到控制台。编译并运行,选中Push via storyboard,然后点击Debug bar上的"pause"按钮。

在终端打出以下内容并重新运行:

1
po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]

得到类似下面的内容:
035.png

这告诉你UINavigationController的第一个视图控制器是一个TableViewController,你可以选择如何推出控制器。第二个view controller是DemoMessagesViewController,或者你已经调试过的view controller。

这个例子似乎不怎么令人兴奋,但如果你的导航控制器中有几个view controller,或者弹出视图中有tab bar控制器,那么想要弄清楚这些view controller如何工作, 这个功能就非常有用了。

Printing the View Hierarchy(打印视图层次)

如果你更喜欢文本化的视图层次,那你可以使用UIView旧的私有recursiveDescription。这个方法打印出来的视图层次非常类似于上边描述的view controller层次。

打开Views\JSQMessagesCollectionViewCellOutgoing.m 并在awakeFromNib中添加一个断点。

036.png

编译并运行,然后选择Push via Storyboard。调试器有问题了,因为加载了JSQMessagesCollectionViewCellOutgoing。现在在控制台输入以下代码:

1
po [self.contentView recursiveDescription]

这将打印出 JSQMessagesCollectionViewCellOutgoing的contentView层次, 看起来像这样:

037.png

这是基本的,但可以帮你调试iOS 8之前的视图层次。

Using debugQuickLookObject(使用debugQuickLookObject)

最后,Xcode5.1引入了Debug Quick Look功能。如果你已经做好了调试的准备,但不大想知道某段代码如何实现对象的特定外观,那么这时候这个功能就非常有用了。

你的自定义类可以实现debugQuickLookObject方法,并返回任何由Xcode展示的内容。此外,如果你已经正进行调试,并且已经有了想要查看的对象,你可以使用快速查看功能,并且Xcode会以可视化形式表示对象。

比如,NSURL对 debugQuickLookObject的实现返回了一个带有URL 的UIWebView,你可以真实看到URL背后的东西。

关于使用Quick Look调试的更多信息,请查看相关文档

下一步

以上是关于实时调试的内容,它是一个可以帮助节省大量时间的工具,非常好用。

如果你想寻找一些更高级、功能更全面的工具,可以试试Reveal(付费),它要比Xcode的视图调试强大很多。你可以查看我们相关主题的Tech Talk


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jeffasd/article/details/51004667

智能推荐

node.js云学堂微信小程序学习系统的设计与实现毕业设计源码011735_基于微信平台的《javascript程序设计》学习系统的设计与实现-程序员宅基地

文章浏览阅读246次。用户:免费好课、直播公开课、课程信息推荐、云学堂资讯、精选好课管理员:首页、用户管理、课程信息管理、精选好课管理、直播公开管理、免费分类管理、云学堂资讯管理_基于微信平台的《javascript程序设计》学习系统的设计与实现

【解决Anaconda3安装问题】conda --version 不是内部命令、没有script文件_conda --version没反应-程序员宅基地

文章浏览阅读9.7k次,点赞11次,收藏9次。这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Ma..._conda --version没反应

flex绑定数据-程序员宅基地

文章浏览阅读664次。在使用Flex开发的过程中,数据绑定是一定会遇到的,这种技术简单,又有点好玩,重要的是它让开发变得简单了。 在Flex中,数据绑定的方式有这么三种:直接在“{}”中填写绑定变量 使用标签绑定 使用ActionScript中的BindingUtils类绑定 示例1中的绑定方式即是第一种绑定方式,在“{}”中直接填写inputUnit.text,表

超融合、软件定义存储(SDS)、分布式存储以及Server SAN的区别与联系_部署方式包括集中式存储、分布式存储、超融合等-程序员宅基地

文章浏览阅读5.7k次。一时让人眼花缭乱的技术概念存储设备一直作为计算机系统的重要组成部分,过去很长一段时间,用户习惯于使用 SAN 存储作为保存企业关键业务数据的不二选择。基于 SAN 存储为核心的三层式基础架构(服务器-存储网络-存储设备),成为企业中最常用的基础架构,也称作传统架构。互联网的出现,信息量呈现爆炸式增长,人类产生数据的速度超越了以往所有时代的总和,需要存储的数据量也是急剧地增长。大数据,人工智能,物联网等新技术出现,对存储提出了新的需求。于是市面涌现了一系列的关于存储的新的技术概念和名词(包括 软件定义存储_部署方式包括集中式存储、分布式存储、超融合等

【Unity3d】百度AI人脸识别实例——描绘人脸特征点_unity 如何判断texture2d 是否黑色-程序员宅基地

文章浏览阅读5.1k次。上一篇文章介绍了在Unity3d中使用百度AI人脸识别功能,本文将用一个描绘人脸特征点的程序来讲解对SDK的调用。首先我们需要搭建一个简单的场景:一个开始测试的按钮,一张供测试和绘制特征点的图片,和显示debug信息的文字框: 然后新建一个叫FaceDetector的脚本,定义变量:public Text debugInfo; // 显示d_unity 如何判断texture2d 是否黑色

filehelper java_Caused by: java.nio.file.FileSystemException: ..... : 打开的文件过多-程序员宅基地

文章浏览阅读1k次。在高并发处理图片的时候出现这个错误。18:29:37.993 [pool-9-thread-8] ERROR cn.bywin.cbvsp.service.ImageSevice - 切图出错!!javax.imageio.IIOException: Can't create cache file!at javax.imageio.ImageIO.createImageOutputStream(I..._filesystemexception 打开的文件过多

随便推点

C语言实验4:指针-程序员宅基地

文章浏览阅读1.5k次,点赞39次,收藏18次。指针是一个变量,其值是另一个变量的地址。通过指针,可以直接访问存储在该地址上的数据。

SQL 数据库 学习 024 查询-07 order by 的用法 --- 以某个字段排序_sql使数据按字段排序-程序员宅基地

文章浏览阅读1.3w次。我的电脑系统:Windows 10 64位SQL Server 软件版本: SQL Server 2014 Express 本篇博客里面使用了 scott 库,如何你现在还没有添加这个库到你的服务器里面,请在查看本篇博客前,访问这篇博文来在你的服务器里面附加scott库。order by — 以某个字段排序例子:select * from emp order by sal; --默认_sql使数据按字段排序

解决360浏览器不支持IDM下载的问题_360下载失败怎么用idm安装-程序员宅基地

文章浏览阅读4.5w次,点赞2次,收藏2次。像360安全浏览器和360极速浏览器的设置中,下载工具都只能选择自己。不能选择IDM下载。 如图: 如何让它们支持IDM下载呢? 在IDM的文件夹中,可以看到一个扩展文件,将它拖动的浏览器中进行安装即可。 如图: 然后打开IDM,可以看到360安全/技术浏览器了。如果没有手动添加浏览器。 然后就可以用IDM下载了。..._360下载失败怎么用idm安装

scala方法中的变量_Scala中的变量-程序员宅基地

文章浏览阅读405次。scala方法中的变量 Scala变量 (Scala variables)A variable is named a reference to a memory location. The location stores the data that is used by the program. 变量被称为对存储位置的引用。 该位置存储程序使用的数据。 Based on the data t..._scala 方法 变量

研报回测:华泰期货《CTA 量化策略因子系列(二):动量因子》_华泰期货cta量化策略因子-程序员宅基地

文章浏览阅读5.9k次,点赞4次,收藏17次。我们都知道做投资最难的地方在于投资逻辑是否准确,如何验证逻辑的准确性是一门工程,从工科思维考虑就是通过历史数据做回测验证,以检验投资逻辑在历史中的表现,从而衡量投资逻辑的有效性。本文从华泰期货研报《20170925-华泰期货-CTA量化策略因子系列(二):动量因子》入手,去论证动量因子是否有效。一、准备巧妇难为无米之炊,首先我们需要准备成交量、动量和收益率的数据,收益率我们采用每天的涨跌幅来计..._华泰期货cta量化策略因子

软件项目全套通用资料(规格说明书~详细设计~测试计划~验收报告)-程序员宅基地

文章浏览阅读503次,点赞9次,收藏7次。在软件开发过程中,文档资料是非常关键的一部分,它们帮助团队成员理解项目需求、设计、实施、测试、验收等各个环节,确保项目的顺利进行。以下是针对您提到的各个阶段的文档资料概述:

推荐文章

热门文章

相关标签