How to observe change of API request status in Swift?

63 Views Asked by At

I am working on a project and I am sending a GET Request to an API URL in my project. (As follows)

Actually everything here works for me. But the problem is; When I first send the request, the "Status" value comes as -proceeding-. After a while it becomes -completed-. (Because I'm waiting for a render in the API)

My question is; How can I know when this status value changes from proceeding to completed? Because I want to do a different action when completed. Any idea about that ?

    func fetchURL(url: String) {
    
    let apiUrl = URL(string: url)!

    let session = URLSession.shared

    let task = session.dataTask(with: apiUrl) { (data, response, error) in
        
        if let error = error {
            print("DEBUG: - Error: \(error)")
            return
        }
        guard let data = data else {
            print("DEBUG: - No data received")
            return
        }

        do {
            
            let decoder = JSONDecoder()
            let dustResponse = try decoder.decode(FetchData.self, from: data)
            
            print("DEBUG: - Status: \(dustResponse.detail.status)")
            print("DEBUG: - Message: \(dustResponse.detail.message)")
        } catch {
            print("DEBUG: - Error decoding JSON: \(error)")
        }
    }
    task.resume()
    
}
1

There are 1 best solutions below

0
Domique 623 On

As the process is made by the server of your API you can't really know when it has finished. I would suggest to see if you have a way to have some kind of web socket to be notified when the processing is finished. If you don't, you could request the status every x seconds to see if the processing is finished:

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func APIFetchResult(apiUrl: URL) async -> FetchData? {
    return await withCheckedContinuation({ (result: CheckedContinuation<Continuation?, Never>) in
       let session = URLSession.shared

       let task = session.dataTask(with: apiUrl) { (data, response, error) in
           if let error = error {
              print("DEBUG: - Error: \(error)")
              result.resume(returning: nil)
           }
           guard let data = data else {
              print("DEBUG: - No data received")
              result.resume(returning: nil)
           }

           do {  
              let decoder = JSONDecoder()
              let dustResponse = try decoder.decode(FetchData.self, from: data)
            
              print("DEBUG: - Status: \(dustResponse.detail.status)")
              print("DEBUG: - Message: \(dustResponse.detail.message)")
              result.resume(returning: dustResponse)
           } catch {
              print("DEBUG: - Error decoding JSON: \(error)")
              result.resume(returning: nil)
           }
       }
       task.resume() 
    })
}


let finalResult: FinalResultType? = nil

while finalResult == nil {
    finalResult = await APIFetchResult(apiUrl: apiUrl)
    await Task.sleep(5_000_000_000) // wait 5 seconds before re-doing the request
}

// do whatever you want after

In this piece of code we:

  1. Create an await/async version of your fetchURL function by using the native withCheckedContinuation function of the Swift's standard library.
  2. Call it every five second + execution time and do that until finalResult is defined.

Hope this will help you!