There are many different ways to do this. The right answer depends on your particular use case, and the way you've designed you API interaction. NSOperations have a great cancel / dependency management / completion workflow, so if you're able to place your API interactions in an NSOperationQueue that may be the best way forward. Another possibility I use for some more simple interactions is to simply keep a reference to the NSURLSessionTasks that correspond to a particular view interaction of view controller, and cancel them as needed. For example:
//: Playground - noun: a place where people can play
import UIKit
class MyViewController: UIViewController, UISearchBarDelegate {
var tasks = [NSURLSessionTask]()
let client = MyAPIClient()
deinit {
cancelAllTasks()
}
func cancelAllTasks() {
tasks.forEach { $0.cancel() }
}
func cancelAllSearchTasks() {
tasks.filter({ $0.taskDescription == MyAPIClient.TaskDecription.search.rawValue }).forEach { $0.cancel() }
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
// Cancel previous search as user types a new search
cancelAllSearchTasks()
guard let text = searchBar.text else {
return
}
tasks.append(client.search(text) { [weak self] results in
// ...
})
}
}
class MyAPIClient {
enum TaskDecription: String {
case search
}
let session = NSURLSession()
func search(text: String, completion: (result: [String]) -> Void) -> NSURLSessionTask {
let components = NSURLComponents()
components.scheme = "http"
components.host = "myapi.com"
components.queryItems = [NSURLQueryItem(name: "q", value: text)]
guard let url = components.URL else {
preconditionFailure("invalid search url")
}
let task = session.dataTaskWithURL(url) { (data, response, error) in
// ...
completion(result: ["results", "from", "api", "go", "here!"])
}
task.resume()
task.taskDescription = TaskDecription.search.rawValue
return task
}
}
Here, when the view controller is deallocated, we cancel all the NSURLSessionTasks that are related to this controller. We also cancel any existing "search" api tasks as the user types in the search bar so that we aren't making "stale" api calls.
Of course this is a fairly simple example but you get the idea- it's good to be smart about the amount of network calls your application is making and cancel them if they are no longer needed!
NSBlockOperation
. It has support for cancellation. – Scathingvar shouldIBeDead : Bool
, and set ittrue
once you hit cancel, and on the completion block call useguard shouldIBeDead else{//execute code}
– AgoutiNSBlockOperation
is not appropriate since the OPs "task" is asynchronous. ANSBlockOperation
executes one or more synchronous tasks. Additionally, there's no built-in mechanism for NSOperations which transfer the result of one operation to the dependent operation. It's possible to workaround this, but it's unduly elaborate and error prone. – Fishback