How do I defer code to the next run loop pass?

Sometimes, I need some code to skip a run loop pass. For example, I'm closing a sheet that animates out and then run a heavy synchronous operation. To prevent the synchronous operation from making the animation stutter, I use DispatchQueue.main.async to defer the code to the next run loop. Example.

What would be the way to handle this now with the new concurrency features?

It's unclear to me whether await Task.yield() would do the same thing.

2 Likes

Is it even an issue anymore? If your synchronous operation isn’t @MainActor the system runs it on a separate thread now anyway doesn’t it? Maybe I misunderstood the WWDC sessions…

Here’s some advice I found immediately after my prior post.

Both operations are on the @MainActor.

Isn’t having long-running operations on @MainActor a design flaw? “Never block the main thread.” is still an axiom in this new concurrency world right?

I didn't say long-running. I would recommend looking at the linked example as it makes it clearer: I'm closing a sheet that animates out. The closing action happens on the @MainActor. I don't control the animation as it's a NSOpenPanel. Immediately in the completion handler, I open another sheet (still in the @MainActor). If I don't put the new sheet opening call in a DispatchQueue.main.async, the first sheet closing animation stutters. Skipping a run loop pass usually fixes small animation issues like this.

1 Like

Did you try Task { ... } ?

I haven't tried anything yet. There are probably multiple solutions that will work, but I'm looking for the most correct one.