I was stumbled upon RunLoop.current.run(until: Date()) string in ViewController unit testing tutorial.
In article the author wrote: “ 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.”
Here the code:
class CreateOrderViewControllerTests: XCTestCase
{
// MARK: - Subject under test
var sut: CreateOrderViewController!
var window: UIWindow!
// MARK: - Test lifecycle
override func setUp()
{
super.setUp()
window = UIWindow()
setupCreateOrderViewController()
loadView()
}
override func tearDown()
{
window = nil
super.tearDown()
}
// MARK: - Test setup
func setupCreateOrderViewController()
{
let bundle = Bundle.main
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
sut = storyboard.instantiateViewController(withIdentifier: "CreateOrderViewController") as? CreateOrderViewController
}
func loadView()
{
window.addSubview(sut.view)
RunLoop.current.run(until:Date())
}
func testCursorFocusShouldMoveToNextTextFieldWhenUserTapsReturnKey()
{
// Given
// Scroll to the top of table view so the first text field is visible and can actually become first responder
let firstSectionIndex = 0
let firstRowIndex = 0
sut.tableView.scrollToRow(at: IndexPath(row: firstRowIndex, section: firstSectionIndex), at: .bottom, animated: false)
// When
let currentTextField = sut.textFields[0]
let nextTextField = sut.textFields[1]
currentTextField.becomeFirstResponder()
_ = sut.textFieldShouldReturn(currentTextField)
// Then
XCTAssert(!currentTextField.isFirstResponder, "Current text field should lose keyboard focus")
XCTAssert(nextTextField.isFirstResponder, "Next text field should gain keyboard focus")
}
I read a few articles about RunLoop, and tried to replace RunLoop.current.run(until:Date()) with
RunLoop.current.run(until:Date(timeIntervalSinceNow: 30)).
and saw that all 30 seconds xcode did not proceed to the next process.
Then I conducted experiment with assigning view to window on background concurrent thread with RunLoop.current.run(until:Date(timeIntervalSinceNow: 30)).
It also didn’t call any other processes on any threads for 30 seconds, that is, the system waited 30 seconds and at that time the process that was already running, it was being finalized, and again any other processes on any threads haven't been called for 30 seconds.
Then I looked on what thread the viewController initialization and window.addSubview() processes are running - it is Thread 1 Queue : com.apple.main-thread (serial), then I looked on what thread test functions are running this is also Thread 1 Queue : com.apple.main-thread (serial). Due to it is serial it is impossible that test functions is executing before viewController initialization and window.addSubview() processes are done. But some people wrote that it could be, when and why?