【问题标题】:Why is runloop called when testing为什么测试时调用runloop
【发布时间】:2019-08-26 17:51:03
【问题描述】:

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

例如在this article 和这个open source project 中。

文章中给出的解释是

RunLoop.current.run(until: Date()) 语句确保与当前线程关联的运行循环有足够的时间让绘图操作完成

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

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

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

【问题讨论】:

  • 我认为这会导致运行循环运行一次。在它完成一个循环后,会经过一些非零的时间,并且当前时间将大于Date(),从而导致runloop不再重复。

标签: ios swift integration-testing runloop


【解决方案1】:

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

我想我们是从实验中知道的。更“正确”的做法是:

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

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

我读了几篇关于运行循环的文章,在我看来,添加这行代码的原因是为了启动应用程序。貌似appDelegate一般会自动触发或者启动run loop,但是由于我们是在测试,所以需要自己触发run loop。

不,应用委托不会启动运行循环。 The function UIApplicationMain 设置应用程序并启动运行循环。如果你新建一个Objective-C项目,你会发现main.m中的main函数调用了UIApplicationMain。在典型的 Swift 项目中,附加到应用委托的 the @UIApplicationMain attribute 告诉 Swift 编译器在 AppDelegate.o 中生成等效代码(调用 UIApplicationMainmain 函数)。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 2013-06-20
    • 1970-01-01
    • 2012-05-21
    • 2014-05-11
    • 2010-10-27
    • 2011-09-16
    相关资源
    最近更新 更多