skip to Main Content

I’m having some compilation warnings using Xcode 14.2/swift 5.7 (future errors in swift 6).

I’ve some async function tests in a unit test target which include some code to process UI changes in the main loop.

There are two related warnings:

RunLoop.current.run(until: Date())
// which raises next warning
Class property 'current' is unavailable from asynchronous contexts; currentRunLoop cannot be used from async contexts.; this is an error in Swift 6
CFRunLoopRunInMode(CFRunLoopMode.defaultMode, 0.1, false)
// which raises next warning
Global function 'CFRunLoopRunInMode' is unavailable from asynchronous contexts; CFRunLoopRunInMode cannot be used from async contexts.; this is an error in Swift 6

Here a full function test example.

@MainActor
public class MainViewController: UIViewController {
...
    public func showLoading() {
    }
...
}
...

@MainActor
func testBasic() async throws {
    // GIVEN
     sut = MainViewController(nibName: nil, bundle: nil)
     present(viewController: sut)

    // WHEN
     sut.loadViewIfNeeded()
     sut.showLoading()
     RunLoop.current.run(until: Date())

     sut.hideLoading()
     sut.showNoConnection()
     RunLoop.current.run(until: Date())

    // THEN
     XCTAssertTrue(sut.connectionStatus.isHidden == false)
}

What alternatives would you use at this point to fix the warnings?

Extended question with more details

I understand that swift concurrency actors/Tasks are not in the same conceptual world than Runloops/Threads.
What I would expect to be able to do is to replace the Runloop code with something equivalent to

RunLoop.current.run(until: Date())

but in Tasks/Actors world.

await MainActor.run(forInterval: 0.1)

Or even better, what I would really like to achieve is to replace that piece of code (that Runloop snippet that I’ve copycat from some people unit tests code) that tries to force UI events processing.

2

Answers


  1. Chosen as BEST ANSWER

    So far, my understanding is that Runloop methods have been declared not async safe (which is understandable as it's Thread based), but without adding an async alternative so far.

    So, at the moment, there are no fixes to this warnings, and instead it would be needed to avoid using Runloops in async contexts.

    PD: This question was crossposted in an Apple forum post named How to adapt RunLoop to swift concurrency(async/await)


  2. Just wrap RunLoop.current.run(until: Date()) into a function:

    func runCurrentLoop() {
        RunLoop.current.run(until: Date())
    }
    

    Then you can use runCurrentLoop in asynchronous contexts without warnings.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search