An operation can be in several states, depending on its current execution status.
- Ready: It's prepared to start
- Executing: The task is currently running
- Finished: Once the process is completed
- Canceled: The task canceled
It's important to know that an operation can only execute once. Whenever it's in the finished or canceled state, you can no longer restart the same instance.
Within custom implementations, you need to manually check the canceled state before execution to make sure a task cancels. Do know that a data race can occur when an operation is both started and canceled at the same time. You can read more about data races in blog post
Thread Sanitizer explained: Data Races in Swift.
The OperationQueue will remove the task automatically from its queue once it becomes finished, which happens both after execution or cancellation.
Making use of dependencies
A benefit of using operations is the use of dependencies. You can easily add a dependency between two instances. For example, to start uploading after the content is imported:
let fileURL = URL(fileURLWithPath: "..")
let contentImportOperation = ContentImportOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentImportOperation.completionBlock = {
print("Importing completed!")
}
let contentUploadOperation = UploadContentOperation()
contentUploadOperation.addDependency(contentImportOperation)
contentUploadOperation.completionBlock = {
print("Uploading completed!")
}
queue.addOperations([contentImportOperation, contentUploadOperation], waitUntilFinished: true)
// Prints:
// Importing content..
// Uploading content..
// Importing completed!
// Uploading completed!