Friday, October 7, 2022
HomeiOS Developmentios - Limiting the variety of fetch requests in URLSession with SwiftUI?

ios – Limiting the variety of fetch requests in URLSession with SwiftUI?

everybody, first query right here!
I am utilizing an async picture loader to fetch photographs from a URLRequest, and I am attempting to wrap my code inside an Operation so I can use .maxConcurrentOperationCount for an OperationQueue, as a result of I am imagined to restrict the variety of downloads to three at a time.. I’ve overriden the Operation class to try to help async downloads, nevertheless, I am not in a position to obtain this, and I believe it is as a result of my downloading perform is inside a Activity group.

The error i get is as follows:
Invalid conversion from ‘async’ perform of sort ‘(URL?, URLResponse?, (any Error)?) async throws -> Void’ to synchronous perform sort ‘(URL?, URLResponse?, (any Error)?) -> Void’

Listed here are the code snippets:

for the overriden Operation class:

class DownloadOperation: Operation {
    personal var process: URLSessionDataTask!
    init(session: URLSession, downloadTaskURL: URLRequest, completionHandler: ((URL?, URLResponse?, Error?) -> Void)?) {
           // use weak self to stop retain cycle
           process = session.dataTask(with: downloadTaskURL, completionHandler: { [weak self] (URLRequest, response, error) in
                set the operation state to completed as soon as
                the obtain process is accomplished or have error
               self?.state = .completed
    enum OperationState : Int {
            case prepared
            case executing
            case completed

    personal var state : OperationState = .prepared {
          willSet {
              self.willChangeValue(forKey: "isExecuting")
              self.willChangeValue(forKey: "isFinished")
          didSet {
              self.didChangeValue(forKey: "isExecuting")
              self.didChangeValue(forKey: "isFinished")
      override var isReady: Bool { return state == .prepared }
      override var isExecuting: Bool { return state == .executing }
      override var isFinished: Bool { return state == .completed }
    override func begin() {
         if the operation or queue received cancelled even
         earlier than the operation has began, set the
         operation state to completed and return
         if(self.isCancelled) {
             state = .completed
         // set the state to executing
         state = .executing
         // begin the downloading

     override func cancel() {
         // cancel the downloading

and right here is me attempting to make use of it inside a process within the loader perform:

  public func loadImage(_ urlRequest: URLRequest) async throws -> UIImage {
        if let standing = photographs[urlRequest]{
            swap standing{
            case .fetched(let picture):
                return picture
            case .inProgress(let process):
                return strive await process.worth
            case .failure(let error):
                self.hasError = true
                self.error = error as? InternetError
        let process: Activity<UIImage, Error> = Activity {
            do {
                let imageQueue = OperationQueue()
                imageQueue.maxConcurrentOperationCount = 3
                let operation = DownloadOperation(session: URLSession.shared, downloadTaskURL: urlRequest, completionHandler: {_, response ,_ in
                    let (imageData, response) = strive await URLSession.shared.information(for: urlRequest)

                    guard let httpResponse = response as? HTTPURLResponse,
                          httpResponse.statusCode == 200 else {
                        throw InternetError.invalidServerResponse
                    guard let picture = UIImage(information: imageData) else {
                        throw InternetError.noInternet
               // return picture
            catch {
                self.hasError = true
                photographs[urlRequest] = .failure(error)
                print("error caught in Loader")
                let picture = UIImage(systemName: "wifi.exclamationmark")!
                return picture
            photographs[urlRequest] = .inProgress(process)
            var picture = strive await process.worth
            if let imageFromCache = imageCache.object(forKey: urlRequest as AnyObject) as? UIImage {
                picture = imageFromCache
                return picture
            photographs[urlRequest] = .fetched(picture)
            //storing picture in cache
            imageCache.setObject(picture, forKey: urlRequest as AnyObject)
            return picture

I’d admire any assist about this! Thanks!!



Please enter your comment!
Please enter your name here

Most Popular

Recent Comments