Task cancellation behaviour

Hi everyone,

I believe this should be a simple and expected default behavior in a real-world app, but I’m unable to make it work: 1. I have a View (a screen/page in this case) that calls an endpoint using async/await. 2. If the endpoint hasn’t finished, but I navigate forward to a DetailView, I want the endpoint to continue fetching data (i.e., inside the @StateObject ViewModel that the View owns). This way, when I go back, the View will have refreshed with the fetched data once it completes. 3. If the endpoint hasn’t finished and I navigate back to the previous screen, I want it to be canceled, and the @StateObject ViewModel should be deinitialized.

I can achieve 1 and 3 using the .task modifier, since it automatically cancels the asynchronous task when the view disappears:

view
  .task { await vm.getData() }

I can achieve 1 and 2 using a structured Task in the View (or in the ViewModel, its the same behavior), for example:

.onFirstAppearOnly {
  Task { away vm.getData() }
}

onFirstAppearOnly is a custom modifier that I have for calling onAppear only once in view lifecycle. Just to clarify, dont think that part is important for the purpose of the example

But the question is: How can I achieve all three behaviors? Is this really such an unusual requirement?

My minimum deployment target is iOS 15, and I’m using NavigationView + NavigationLink. However, I have also tried using NavigationStack + NavigationPath and still couldn’t get it to work.

Any help would be much appreciated. Thank you, folks!

Task cancellation behaviour
 
 
Q