Async func is invoking with delay from UI thread

Hello!

I have founded that .task modifier on View or using Task {} in .onAppear{} modifier has a delay about 20-30 ms to switch context. But if I'm using Task.detached with .high priority, so there is no any delay and it works fast.

The second problem is when async func from ViewModel was called in Task.detached from .onAppear modifier there is still delay about 20-25 ms. Is there any fix for it?

1 Like

This would be expected. .task { Task { } } inherits the @MainActor isolation, and so runs on the next loop of the main run loop at the earliest. .task { Task.detached { } } runs on the default executor and so may begin execution sooner.

4 Likes

Thanks for explanation. But we start collecting metrics from .onAppear and there is still delay from .onAppear to .task. Is it possible to call async func from .onAppear without delay?

I'm not sure async/await could be faster than normal execution, there are many factors that can influence that.

Btw why you need it to be so fast? :thinking:

We are developing a tool to measure performance. So we need to make it tool as accurate as it could be.

I find myself struggling with applying Swift concurrency (especially actors) correctly, so maybe this may be a naive question:

Why are you using Swift concurrency here at all, given that all the code seems to be UI-related and must thus run on the main thread anyway? Why not just

var body: some View {
    .onAppear {
        viewModel.onAppear()
    }
}

ViewModel.onAppear() may be calling into asynchronous code, of course.

Edit: oh, this would probably just shift the problem to some other location in the code.

There is not a problem if I would create a task in viewModel layer) Actually, that's what I did)