为什么测试的时候会调用runloop

Why is runloop called when testing

我经常看到 RunLoop.current.run(until: Date()) 在集成测试中被调用。

例如 this article and in this open source project.

文中给出的解释是

The RunLoop.current.run(until: Date()) statement makes sure the run loop associated with the current thread has ample time to let the drawing operations to complete

如果那是真的,我们为什么不给它更多时间,我们怎么知道 Date() 就足够了?

我阅读了一些关于 运行 循环的文章,在我看来,添加这行代码的原因似乎是为了启动应用程序。似乎 appDelegate 通常会自动触发或启动 运行 循环,但由于我们正在测试,我们需要自己触发 运行 循环。

我可能缺少对线程或 运行 循环的一些基本理解,但我希望有人能提供一些见解。

If that is true why wouldn't we give it more time, how do we know that Date() is enough?

我想我们是通过实验知道的。更“正确”的方法是:

  1. 安装一个 运行 循环观察器,它以某种方式检测何时布局和绘制视图。
  2. 运行 运行 无限循环(直到 Date.distantFuture)。
  3. 在第1步安装的观察者中,检测到视图已经布局绘制时调用CFRunLoopStop(CFRunLoopGetMain())

然而,当更简单的方法有效且不太可能失败时,这需要做很多额外的工作,而不仅仅是 RunLoop.current.run(until: Date())

I read a few articles about the run loop and it seems to me like the reason that line of code is added is to start the app. It seems like the appDelegate usually automatically triggers or starts the run loop, but since we are testing we need to trigger the run loop ourselves.

不,应用委托不会启动 运行 循环。附加到应用程序委托的 The function UIApplicationMain sets up the app and starts the run loop. If you create a new Objective-C project, you will find that the main function in main.m calls UIApplicationMain. In a typical Swift project, the @UIApplicationMain attribute 告诉 Swift 编译器在 AppDelegate.o.

中生成等效代码(调用 UIApplicationMainmain 函数)

I might be missing some fundamental understand of threads or run loops but I hope that someone can give some insight.

应用程序的大部分生命周期都在 运行 循环中度过,循环(简化)有以下阶段:

  1. 等待一个事件。有很多事件源,包括应用程序启动、触摸、定时器、加速度计、GPS、进入后台、返回前台等等。
  2. 处理事件,通常是调用您编写的代码。
  3. 如果任何视图设置了 needsLayout 属性,请布置视图层次结构的适当部分(包括发送 layoutSubviews 消息)。
  4. 如果任何视图设置了 needsDisplay 属性,绘制这些视图(通过发送 drawRect: 消息)。
  5. 返回步骤 1。