测量在 UIViewController 及其所有子视图中绘制视图需要多长时间

Posted

技术标签:

【中文标题】测量在 UIViewController 及其所有子视图中绘制视图需要多长时间【英文标题】:Measuring how long it takes to draw a view in a UIViewController and all its subviews 【发布时间】:2020-07-05 16:23:37 【问题描述】:

起初我想使用 -viewWill/DidAppear 但我需要知道所有可能的视图控制器中所有后续更新的时间,所以我想出了一个 UIView 子类,它始终是每个控制器中的根视图并有一个实例为其父 VC 变量并在 -drawRect 中执行此操作:

- (void)drawRect:(CGRect)rect

   if (self.parentViewController)  
      [self.parentViewController resetTime];
      [self.parentViewController performSelector:@selector(measureTimeMethod) withObject:nil afterDelay:.0];
   

似乎有点工作,但我可以确定这会在下一个事件周期被调用吗?我相信一定有更好的方法来做到这一点。

【问题讨论】:

我认为 performSelector: with delay 会在所有子视图都被绘制之后在下一个事件周期调用选择器。问题是,我不确定。当我开发这个应用程序时,我想看看每个解决方案如何影响速度。我需要不断地从数据库中获取东西,屏幕可能会变得太复杂,我想知道什么解决方案是正确的,什么想法是错误的,我应该在哪里使用延迟加载,我应该在哪里将内容保存在内存缓存中等等等等. 【参考方案1】:

您可以(并且应该)使用 Inspector 来衡量您的 CoreGraphics 例程的时序问题,以构建您的用户界面。

如果您在 -drawRect: 类方法中有大量的绘图调用,那么它肯定会比调用更少的更慢。这就是为什么Apple建议在图形没有连续变化或者即使drawRect为空的情况下避免使用这种方法的原因。您必须绘制的像素越少,下一个绘制周期中的图层和元素就越少,它就会越快。考虑减少 Rect 的大小以绘制绝对需要的范围,这将非常固定它。如果 drawRect 真的是满足您需求的方式,请重新考虑您的设计模式。也许您想编写在开始时绘制一次并且仅在之后更新大小和位置的类。

如果您想制作更快的 UI:建议改用 -(void)layoutSubviews 并更新预定义布局/子层 UI 元素的框架。

如果你真的要测量:一次测量只会给你一个关于改进的粗略线索,但比在你的对象模型上执行选择器更精确。

改为使用

#include <mach/mach_time.h> 

mach_absolute_time(); 

将输出缓存在全局中以计算时间差异

在你的-drawRect 中遍历布局代码无论如何都会给你错误的时间。 DrawRect 用于绘图。换句话说,您可以将 if 语句放在 -(void)layoutSubviews-(void)layoutSublayers 中。

ios 上,您的 UI 通常始终在 Main Thread 中运行,您可以在分配和启动包含您要检查的内容的子视图之前和之后进行测量。如果您想在运行时测量绘图的变化,您将需要弄清楚提到的绘图方法是什么时候调用的。

另一个极端简单的解决方案是NSLog(@"t"); 并在调试器中观察相应的时间打印。

【讨论】:

我想测量在视图控制器中绘制或重绘所有子视图所需的总时间。这些子视图可能是表格视图、滚动视图、各种控件和图像或标签。我需要在开发应用程序时对其进行测量。而且我想在每次更改代码后始终查看这些数字,而不是偶尔在我想使用 Instruments 时查看这些数字。如果所有子视图,即使是来自子视图控制器的子视图都在单个事件周期中绘制,并且如果发送到 perfomSelector: 的选择器在下一个事件周期中执行,我的解决方案可能会起作用。 好吧,那么 CADisplayLink 是您之前想知道的,因为您希望在不到一个周期(即 60 或 120Hz)内进行绘制。您的瓶颈将是用于缓存获取的数据和相应的工作线程(请求缓存解析)的内存分配。从开发实时运动序列器,在渲染时从外部设备和网络永久获取数据,我仅在启动时使用 drawRect,但大多数情况下根本不使用。只是说,drawRect 会降低你的性能,因为即使你可以调用它也不意味着永久绑定到 CADisplayLink。 检查器在 Xcode 中运行,显示以 120Hz 的百分比表示的渲染压力。

以上是关于测量在 UIViewController 及其所有子视图中绘制视图需要多长时间的主要内容,如果未能解决你的问题,请参考以下文章

UITabBarItem 及其 UIViewController - 一个复杂的问题

Cortex-M系统中断延迟及其测量方法

测量峰值堆栈指针值及其 PC 位置

DNA甲基化及其测量方法(转)

测量执行时间和使用的内存

[信息论与编码理论专题-3]:信源及其信息测量