I'm using an async image loader to fetch images from a URLRequest, and I'm trying to wrap my code inside of an Operation so I can use .maxConcurrentOperationCount for an OperationQueue, because I'm supposed to limit the number of downloads to 3 at a time.
I've overriden the Operation class to try and support async downloads, however, I'm not able to achieve this, and I think it's because my downloading function is inside of a Task group.
The error i get is as follows:
Invalid conversion from 'async' function of type '(URL?, URLResponse?, (any Error)?) async throws -> Void' to synchronous function type '(URL?, URLResponse?, (any Error)?) -> Void'
Here are the code snippets:
for the overriden Operation class:
class DownloadOperation: Operation {
    private var task: URLSessionDataTask!
    
    init(session: URLSession, downloadTaskURL: URLRequest, completionHandler: ((URL?, URLResponse?, Error?) -> Void)?) {
           super.init()
           
           // use weak self to prevent retain cycle
           task = session.dataTask(with: downloadTaskURL, completionHandler: { [weak self] (URLRequest, response, error) in
               
   
               
              /*
                set the operation state to finished once
                the download task is completed or have error
              */
               self?.state = .finished
           })
       }
    
    enum OperationState : Int {
            case ready
            case executing
            case finished
        }
    private var state : OperationState = .ready {
          willSet {
              self.willChangeValue(forKey: "isExecuting")
              self.willChangeValue(forKey: "isFinished")
          }
          
          didSet {
              self.didChangeValue(forKey: "isExecuting")
              self.didChangeValue(forKey: "isFinished")
          }
      }
      
      override var isReady: Bool { return state == .ready }
      override var isExecuting: Bool { return state == .executing }
      override var isFinished: Bool { return state == .finished }
    
    
    override func start() {
         /*
         if the operation or queue got cancelled even
         before the operation has started, set the
         operation state to finished and return
         */
         if(self.isCancelled) {
             state = .finished
             return
         }
         
         // set the state to executing
         state = .executing
         
         print("downloading")
               
         // start the downloading
         self.task.resume()
     }
     override func cancel() {
         super.cancel()
       
         // cancel the downloading
         self.task.cancel()
     }
}
and here is me trying to use it inside of a task in the loader function:
  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 imageQueue = OperationQueue()
                imageQueue.maxConcurrentOperationCount = 3
                
                let operation = DownloadOperation(session: URLSession.shared, downloadTaskURL: urlRequest, completionHandler: {_, response ,_ in
                    let (imageData, response) = try await URLSession.shared.data(for: urlRequest)
                    guard let httpResponse = response as? HTTPURLResponse,
                          httpResponse.statusCode == 200 else {
                        throw InternetError.invalidServerResponse
                    }
                    guard let image = UIImage(data: imageData) else {
                        throw InternetError.noInternet
                    }
                    
                })
                imageQueue.addOperation(operation)
                
                
                
               // return image
            }
            catch {
                self.hasError = true
                images[urlRequest] = .failure(error)
                print("error caught in Loader")
                let image = UIImage(systemName: "wifi.exclamationmark")!
                return image
            }
        }
        
        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
        }
    }
}
I would appreciate any help about this! Thank you!!
 
     
    
