URLSession in Swift

Janvi Arora
4 min readMar 3, 2023

--

In Swift, URLSession is a powerful framework for networking that allows developers to send and receive data from the web. URLSession provides a range of functionalities that enable developers to interact with web-based services and download data, including images, audio, and video files. In this way, it enables the development of robust and dynamic applications.

URLSession can be used to perform HTTP/HTTPS requests, download data from a URL, and upload data to a web service. It can be used for both background and foreground network requests, and it supports a range of authentication and security features.

URLSession has three types of tasks: data tasks, download tasks, and upload tasks.

  1. Data tasks: This type of task is used for sending and receiving data in the form of Data objects.
  2. Download tasks: This type of task is used to download files from the web. It supports resumable downloads, so if the download is interrupted, it can be resumed from where it left off.
  3. Upload tasks: This type of task is used to upload data to a web service. It supports uploading data in the form of files or streams.

URLSession also provides a range of options for configuring the behavior of network requests, including cache policy, timeout interval, and cookie policy.

To use URLSession, you need to create a URLSession object and then create a task to perform the desired operation. You can then start the task, and it will run asynchronously in the background.

URLSession provides a range of delegate methods that allow you to handle the response from the web service, track the progress of the task, and handle errors.

Overall, URLSession is a powerful framework for networking that provides a range of functionalities for sending and receiving data from the web. It enables developers to create robust and dynamic applications that interact with web-based services and download data, including images, audio, and video files.

enum DataError: Error {
case invalidData
case invalidResponse
case message(_ error: Error?)
}

class APIManager {
static let shared = APIManager()
private init() { }

let url = URL(fileURLWithPath: "anyURL")

// @escaping is used here, because this is a background task.
// If you write a print statemnet after the dataTask completes, i.e. after resume(), then it will execute beforehand.
// This happens because it is time consuming task and can not be implemented on main thread.
//@escaping captures data in memeory.

func fetchData(completion: @escaping (Result<[Product], Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data else {
completion(.failure(.invalidData))
return
}
guard let response = response as? HTTPURLResponse, 200 ... 299 ~= response.statusCode else {
completion(.failure(.invalidResponse))
return
}

// JSONDecoder() converts data to model of type Array
do {
let products = try JSONDecoder().decode([Products].self, from: data)
completion(.success(products))
}
catch {
completion(.failure(.message(error)))
}
}.resume()
}
}
  1. First, an enumeration named DataError is defined, which conforms to the Error protocol. It contains three cases: invalidData, invalidResponse, and message which takes an optional Error parameter.
  2. Next, a class named APIManager is defined with a private initializer and a static instance property named shared that returns an instance of the class.
  3. An instance property named url is declared, which holds the URL that will be used to fetch data.
  4. The fetchData function is defined with a completion handler that takes a Result object that contains an array of Product objects or an error.
  5. The fetchData function calls the dataTask(with:completionHandler:) method of the shared URLSession object, passing in the url property and a completion handler that will be executed when the task completes.
  6. Inside the completion handler, the response is checked to ensure that the status code falls within the 200–299 range. If it does not, the completion handler is called with a .invalidResponse error.
  7. Next, the response data is checked to ensure that it is not nil. If it is nil, the completion handler is called with an .invalidData error.
  8. If the response data is not nil, the JSONDecoder is used to decode the data into an array of Product objects. If successful, the completion handler is called with a Result object containing the array of products.
  9. If an error is thrown during the decoding process, the completion handler is called with a .message error that contains the original error.
  10. Finally, the task is started by calling the resume() method on it.

Overall, this code shows how to use URLSession to fetch and decode JSON data from an API. The Result type is used to return either a successful result or an error, and the DataError enumeration is used to define the specific types of errors that can occur during the process.

final class ProductView {
var products: [Product] = []

func fetch() {
APIManager.shared.fetchProducts { response in
switch response {
case .success(let products):
self.products = products
case .failue(let error):
print(error)
}
}
}
}

Keywords used in this code:

  1. enum: Defines a custom error type DataError with cases invalidData, invalidResponse, and message.
  2. static: Defines a class-level property shared of type APIManager, which is a singleton instance of the APIManager class.
  3. private: Ensures that the init() method can only be called from within the APIManager class.
  4. escaping: Indicates that the closure parameter completion may be called asynchronously after the function fetchData has returned.
  5. Result: A Swift built-in enum that represents either a successful result with an associated value or a failure with an associated error.
  6. guard: A control flow statement that executes a set of statements only when a condition is not met, and optionally returns from the current scope.
  7. return: A keyword that exits the current scope and returns a value to the caller.
  8. URLSession: A Foundation class that manages URLSessionTasks, which retrieve the contents of URLs, including text, XML, and binary data.
  9. dataTask(with:completionHandler:): A method of URLSession that creates a task that retrieves the contents of a URL based on the specified URL request object and calls a handler upon completion.
  10. resume(): A method of URLSessionDataTask that starts the task, which calls the completion handler when the task completes or fails.
  11. HTTPURLResponse: A Foundation class that represents an HTTP URL response.
  12. 200 ... 299: A range of HTTP status codes indicating a successful response.
  13. JSONDecoder(): A Foundation class that decodes instances of a data type from JSON objects.
  14. decode(_:from:): A method of JSONDecoder that decodes an instance of the specified type from the given JSON representation.

--

--

Responses (1)