iosswifturlrequestretry-logic

How can I retry a URLRequest.sharedDataTask until the response is 200?


I am new to Swift and currently stuck on exiting a function containing shared.dataTask once the httpResponse is 200. Any suggestions will be appreciated.

func retryFunc(url: String, requestType: String, requestJsonData: Any, retriesLeft: Int) {
    //Function body
    // declarations
    while self.numberOfretries > 0 {
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }            
            
            if let httpResponse = response as? HTTPURLResponse {
                print(httpResponse.statusCode)
                if httpResponse.statusCode == 200 {
                    print("Got 200")
                    self.numberOfretries = 0
                    let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
                    if let responseJSON = responseJSON as? [String: Any] {
                        print(responseJSON)
                    }
                    return
                }
                if httpResponse.statusCode == 500 {
                    print("Got 500")
                    self.numberOfretries -= 1
                    
                    self.retryFunc(url: url, requestType: <request-type>, requestJsonData: json, retriesLeft: self.numberOfretries)
                }
            }
        }
        task.resume()
    }
}
//calling function from another class
func retryFunc(url: <url>, requestType: <type>, requestJsonData: <jsonData>, retriesLeft: <3>)

I need to exit the function on getting 200 but it still continues to run for the number of retries specified while calling the function.


Solution

  • Consider that the while loop is outside of the asynchronous task, so a couple of 100 tasks can be created before the counter is being decremented.

    A better way is to remove the while loop and check for 0 inside the closure – the retriesLeft parameter makes no sense – for example

    func retryFunc(url: String, requestType: String, requestJsonData: Any) {
        //Function body
        // declarations
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
                            
            if let error = error {
                print(error.localizedDescription)
                return
            }
                                
            if let httpResponse = response as? HTTPURLResponse {
               print(httpResponse.statusCode)
               if httpResponse.statusCode == 200 {
                   print("Got 200")
                   do {
                       if let responseJSON = try JSONSerialization.jsonObject(with: data!) as? [String: Any] {
                           print(responseJSON)
                       }
                   } catch { print(error) }
    
               } else if httpResponse.statusCode == 500 {
                   print("Got 500")
                   self.numberOfretries -= 1
                   if self.numberOfretries == 0 { return }
        
                   self.retryFunc(url: url, requestType: requestType, requestJsonData: requestJsonData)
               }
           }
        }
        task.resume()
    }