Asynchronous DataTask Request in Xcode Playground Tutorial
Tags: xcode, urlsession, ios, swift
Published: 2021-03-22 19:51:15

This can be achieved in three simple steps.
- import `PlaygroundSupport` 

- call `PlaygroundPage.current.needsIndefiniteExecution = true`


- Write out your network request
- upon completion of the network request call `PlaygroundPage.current.finishExecution()`

To put this into context i'll be using the Github Jobs api to illustrate the steps above
- Step 1: - 
Add this statement to your playground 

```swift
import Foundation
import PlaygroundSupport
```

- Step 2:- 
Right below the import statements set the needs Indefinite Execution to true 
```swift
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true
```

Good progress so far. As per you needs create your network request, for our tutorial we'll create a [Github Jobs API](https://jobs.github.com/positions.json?description=api) request as follows
 - First we'll define our Struct which implements the Codable protocol and it defines the shape of our response , then we'll make the Network call. 

You file should look like this

```swift
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true
struct GithubJob: Codable {
    var company: String?
   var company_logo: String?
   var company_url: String?
   var description: String?
   var id: String?
   var location: String?
   var title: String?
   var url: String?
}

func fetchGithubJobs(completionHandler: @escaping(Result<[GithubJob],Error>) -> Void) {
    //create an instance of the jsonDecoder
    let jsonDecoder = JSONDecoder()
    //create a dataTask
    let session = URLSession(configuration: .default, delegate: nil, delegateQueue: .main)
    let endpoint = "https://jobs.github.com/positions.json?description=api"
    
    //create a url from the endpoint
    guard let endpointURL = URL(string: endpoint) else {
        return
    }
    //create a request
    var request = URLRequest(url: endpointURL)
    request.httpMethod = "GET"
    
    //create the dataTask
    let dataTask = session.dataTask(with: request) { (data, _, error) in
        //check if error is nil
        guard error == nil else {
            completionHandler(.failure(error!))
            return
        }
        //check if we already have data
        guard let jsonData = data else {
            return
        }
        //try to decode the response
        do {
            let githubJobs = try jsonDecoder.decode([GithubJob].self, from: jsonData)
            print("Jobs are \(githubJobs)")
            completionHandler(.success(githubJobs))
            
            
        } catch {
            print("Something Went wrong")
            completionHandler(.failure(error))
        }
    }
    
    dataTask.resume()
    
}

```

The last step involves us calling our function and then once our function finishes executing calling `PlaygroundPage.current.finishExecution()`

Adding this last step your file should look like the code snippet below.


```swift
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true
struct GithubJob: Codable {
    var company: String?
   var company_logo: String?
   var company_url: String?
   var description: String?
   var id: String?
   var location: String?
   var title: String?
   var url: String?
}

func fetchGithubJobs(completionHandler: @escaping(Result<[GithubJob],Error>) -> Void) {
    //create an instance of the jsonDecoder
    let jsonDecoder = JSONDecoder()
    //create a dataTask
    let session = URLSession(configuration: .default, delegate: nil, delegateQueue: .main)
    let endpoint = "https://jobs.github.com/positions.json?description=api"
    
    //create a url from the endpoint
    guard let endpointURL = URL(string: endpoint) else {
        return
    }
    //create a request
    var request = URLRequest(url: endpointURL)
    request.httpMethod = "GET"
    
    //create the dataTask
    let dataTask = session.dataTask(with: request) { (data, _, error) in
        //check if error is nil
        guard error == nil else {
            completionHandler(.failure(error!))
            return
        }
        //check if we already have data
        guard let jsonData = data else {
            return
        }
        //try to decode the response
        do {
            let githubJobs = try jsonDecoder.decode([GithubJob].self, from: jsonData)
            print("Jobs are \(githubJobs)")
            completionHandler(.success(githubJobs))
            
            
        } catch {
            print("Something Went wrong")
            completionHandler(.failure(error))
        }
    }
    
    dataTask.resume()
    
}

fetchGithubJobs { result in
    switch result {
    case .success(let jobs):
        print("Jobs are \(jobs)")
    default:
        print("Something Went Wrong")
    }
    PlaygroundPage.current.finishExecution()
}

```

Execute this and you should see the Job listing on the debug area.