iOS视图成像解构

在我们开发移动端程序时,难免会遇到这些情况,一些希望展示的控件已经加载了,却因为层次结构的问题被遮挡了;一些不想被显示的控件反而因为视图层级结构没有控制好而显示出来了。遇到这些问题,一个原因是随着开发的进行,视图结构越来越复杂,从展现的角度看,逻辑分析已经不能有效的区分视图结构了,如果对iOS成像的层级结构不能有一个深刻的理解,在我们后期的开发中,将是一个很大的问题。

使用recursiveDescription显示当前视图的详细层级结构

UIView掌管直接屏幕绘图,IOS中几乎所有可视化控件都是UIView的子类。负责渲染区域的内容,并且响应该区域内发生的触摸事件。

UIView的功能

1.管理矩形区域里的内容
2.处理矩形区域中的事件
3.子视图的管理
4.还能实现动画 UIView的子类也具有这些功能

UIView有一个方法recursiveDescription可以显示出当前视图的详细层级结构,可以在代码中直接调用,也可以在GDB中调用,断点后,在GDB中调用时需要借助另一个GDB命令:print-object:即我们常用的po。使用 po [self.view recursiveDescription];即可打印出我们当前的层级结构。

如此,我做了一个测试的demo,视图结构如下:

测试demo

从上图可以看到,有一个Label隐藏在蓝色View下面了。通过上面的方法,我们打印下层次结构。

视图结构

从上图我们可以看到,通过这个命令,我们打印出了当前展示的所有视图结构,像UIButton里包含的UIButtonLabel都打印出来了,很详细也很繁琐,看如此多的结果需要很大的耐心。那有没有更好的方法呢?

DebugView工具

DebugView在GitHub上是开源的,通过这个链接可以得到源码,下面我们来试一试。
使用Cocoa pods

pod 'DebugView', '~> 0.0'

导入DebugView。它是自动的,运行项目即可得到结果。

DebugView

它只会输出可见的控件的详细信息,包括位置,距离等。但是我们之前有一个Label隐藏在蓝色View下面的,是看不到的。如果我们把Label上移,就可以看到了。结果如下:

移动结果

如此看来,DebugView对于我们的视图结果分析还是有很大帮助的。
因为DebugView是自动加载的,如果想取消,可以这么做:

设置取消DebugView

只需要在DebugView-prefix.pch中加入

#define NO_DEBUG_VIEW

就可以了。

知识是在不断的穷举中得到的,显然我们是不满足于这些的。那,除此之外,还有没有更好的方法呢。

利用Xcode来视图调试

首先运行我们的项目,按下底部的Debug View Hierarchy 按钮,或者从菜单中选择Debug > View Debugging > Capture View Hierarchy 来启动视图调试。

启动视图调试

我们会得到如下视图

视图调试

从左到右控件排序:

调整视图间距:调整不同视图间的间距。
展示被剪切的内容:当前展示视图中被剪切的部分。
展示约束:展示选中视图的约束。
重置查看区域:将3D渲染透视图恢复至默认状态。
调整查看模式:选择性地展示3D渲染透视图,比如仅展示内容,仅展示框架以及同时展示内容和框架。
缩小:缩小3D渲染透视图
恢复:将3D渲染透视图恢复至默认尺寸。
放大:放大3D渲染透视图
调整可视视图范围:隐藏视图或展示视图,一步步解析3D渲染视图,向左或者向右滑动滑块儿有相反的效果。

当我们拖动视图时可以很明了的看到视图结构:

视图结构

可以很明显的看到Label在蓝色的View下面。

可能,有些朋友会有疑问,上面的视图都是在storyboard里拖入的,那代码创建的视图是否也可以如此查看呢,下面我们就来试一试。

- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 320, 100, 100)];
btn.backgroundColor = [UIColor purpleColor];
[btn setTitle:@"代码创建的" forState:UIControlStateNormal];
[self.view addSubview:btn];
}

结果如下:

代码实现

更多有趣好玩不八卦的文章,我们后续再谈。

有料