I usually see RunLoop.current.run(until: Date()) called in integration tests.
For example in this article and in this open source project.
The explanation given in the article is
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
If that is true why wouldn't we give it more time, how do we know that Date() is enough?
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.
I might be missing some fundamental understand of threads or run loops but I hope that someone can give some insight.
We know from experimentation, I suppose. A more “correct” way to do it would be:
Date.distantFuture).CFRunLoopStop(CFRunLoopGetMain())when it detects that the views have been laid out and drawn.However, that's a lot of extra work to do instead of just
RunLoop.current.run(until: Date()), when the simpler method works and is unlikely to break.No, the app delegate does not start the run loop. The function
UIApplicationMainsets up the app and starts the run loop. If you create a new Objective-C project, you will find that themainfunction inmain.mcallsUIApplicationMain. In a typical Swift project, the@UIApplicationMainattribute attached to the app delegate tells the Swift compiler to generate equivalent code (amainfunction that callsUIApplicationMain) inAppDelegate.o.An app spends most of its life in the run loop, which (simplified) has these phases:
needsLayoutproperty set, lay out the appropriate sections of the view hierarchy (which includes sendinglayoutSubviewsmessages).needsDisplayproperty set, draw those views (by sendingdrawRect:messages).