What's the best way to avoid starting duplicate tasks?

In SwiftUI, the new task modifier handles creating a new task on a UI action or on view appearance. It also ensures that a task isn't restarted on a second action if the task from the first action is still in progress.

What is the best way of getting the same behavior in non-SwiftUI code? Here's my best attempt:

class Controller: UIViewController {
   var task: Task? = nil

   // ...

   func didTapStart() {
     guard self.task == nil || self.task.isCancelled else { return }

     self.task = Task { .... } 
   }
}

Will this work? Will isCancelled be true when a task successfully completes, or only if it's explicitly cancelled? Is there a better way?

In C# the pattern I used to use was this (adapted to Swift concurrency):

   func didTapStart() {
       disableStartButton();
       Task {
            // ... await whatever
            enableStartButton();
        } 
   }

You could also do things like enable a spinner, show a progress bar, or whatever makes sense. The idea is that it's better to indicate to the user that something happened (visually) and that further UI actions won't do anything rather than let them keep tapping the button and wonder "is it working? did I just make it happen twice? what's going on?"

Terms of Service

Privacy Policy

Cookie Policy