Limiting the number of URLRequests at a time?

Hey everyone! I'm creating a custom Image Loader application and I need to be able to limit the number of URLRequests sent at a time. I have considered using dispatch Semaphores, however, my function to fetch photos is supposed to be asynchronous. I will include the code below. I have also considered to create an Async Operation object but that also did not work out. Does anyone have any suggestions for how to achieve this functionality?

 public func loadImage(_ urlRequest: URLRequest) async throws -> UIImage {

        if let status = images[urlRequest]{

            switch status{

            case .fetched(let image):

                return image

            case .inProgress(let task):

                return try await task.value

            case .failure(let error):

                self.hasError = true

                self.error = error as? InternetError

            }

        }

        

        

        let task: Task<UIImage, Error> =  Task {

            do {

              //  let downloadQueue = DispatchQueue.global(qos: .userInitiated)

               // let downloadGroup = DispatchGroup()

                

                let (imageData, response) = try await URLSession.shared.data(for: urlRequest)

                downloadSemaphore.signal()



               guard let httpResponse = response as? HTTPURLResponse,

                          httpResponse.statusCode == 200 else {

                        throw InternetError.invalidServerResponse

                    }

                

          guard let image = UIImage(data: imageData) else {

                    throw InternetError.noInternet

                }

     

               return image

            }

            catch {

                self.hasError = true

                images[urlRequest] = .failure(error)

                print("error caught in Loader")

                let image = UIImage(systemName: "wifi.exclamationmark")!

                return image

            }



        }

        

        let blockOperation = BlockOperation {

            self.downloadSemaphore.wait()

        }

        

        opeQueue.maxConcurrentOperationCount = 1

        opeQueue.addOperation(blockOperation)

        



        do{

            images[urlRequest] = .inProgress(task)

            var image = try await task.value

            if let imageFromCache = imageCache.object(forKey: urlRequest as AnyObject) as? UIImage {

                image = imageFromCache

                return image

            }

            images[urlRequest] = .fetched(image)

            //storing image in cache

            imageCache.setObject(image, forKey: urlRequest as AnyObject)

            return image

        }

    }

}

There are many ways you can approach this. The approach you’re suggesting seems quite convoluted. I’m not sure why you pulled in both Dispatch semaphores and OperationQueue. Also, from skimming the code I can’t see what limit you’re trying to impose. Is the limit meant to be 1, and hence that’s why you set maxConcurrentOperationCount to 1?

ps Swift concurrency doesn’t have an obvious way to do what you’re trying to do right now. If you search Swift Forums for maxConcurrentOperationCount, you’ll find a number of threads this topic. Honestly, I haven’t yet decided what my own preferred approach for this is.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Limiting the number of URLRequests at a time?
 
 
Q