Chapters

Hide chapters

Concurrency by Tutorials

Third Edition · iOS 16 · Swift 5.7 · Xcode 14

10. Canceling Operations
Written by Scott Grosch

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

With an operation, you have the capability of canceling a running operation as long as it’s written properly. This is very useful for long operations that can become irrelevant over time. For instance, the user might leave the screen or scroll away from a cell in a table view. There’s no sense in continuing to load data or make complex calculations if the user isn’t going to see the result.

The Magic of Cancel

Once you schedule an operation into an operation queue, you no longer have any control over it. The queue will schedule and manage the operation from then on. The one and only change you can make, once it’s been added to the queue, is to call the cancel method of Operation.

Cancelling an Operation Operation isCancelled isFinished = false = false = true isExecuting Operation isCancelled isFinished = true = true = false isExecuting cancel()

There’s nothing magical about how canceling an operation works. If you send a request to an operation to stop running, then the isCancelled computed property will return true. Nothing else happens automatically! At first, it may seem strange that iOS doesn’t stop the operation automatically, but it’s really not.

What does canceling an operation mean to the OS?

  • Should the operation simply throw an exception?
  • Is there cleanup that needs to take place?
  • Can a running network call be canceled?
  • Is there a message to send server-side to let something else know the task stopped?
  • If the operation stops, will data be corrupted?

With just the small list of issues presented in the bullets above, you can see why setting a flag identifying that cancellation has been requested is all that’s possible automatically.

The default start implementation of Operation will first check to see whether the isCancelled flag is true, and exit immediately if it is.

Cancel and cancelAllOperations

The interface to cancel an operation is quite simple. If you just want to cancel a specific Operation, then you can call the cancel method. If, on the other hand, you wish to cancel all operations that are in an operation queue, then you should call the cancelAllOperations method defined on OperationQueue.

Updating AsyncOperation

In this chapter, you’ll update the app you’ve been working on so that an image’s operations are canceled when the user scrolls away from that image.

override func start() {
  main()
  state = .executing
}
override func start() {
  if isCancelled {
    state = .finished
    return
  }

  main()
  state = .executing
}

Canceling a Running Operation

To support the cancellation of a running operation, you’ll need to sprinkle checks for isCancelled throughout the operation’s code. Obviously, more complex operations are going to be able to check in more places than something simple like your NetworkImageOperation.

guard !self.isCancelled else { return }
private var task: URLSessionDataTask?
task = URLSession.shared.dataTask(with: url) {
task?.resume()
override func cancel() {
  super.cancel()
  task?.cancel()
}
guard !isCancelled else { return }
guard !isCancelled else { return }
@State private var operations: [Operation] = []
operations = [downloadOp, tiltShiftOp]
.onDisappear {
  operations.forEach { $0.cancel() }
}

Where to Go From Here?

Having to cancel an operation doesn’t necessarily mean something negative happened. At times you cancel an operation because it’s simply no longer necessary.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now