Lance Samaria
Lance Samaria

Reputation: 19622

How to pass URLSessionTask as a parameter

I have a cell and I'm using URLSessionTask inside of it for some images. When the cell scrolls off of the screen, in prepareForReuse I cancel the task and everything works fine. Because I'm doing several thing with the image once I get it from the task, I want to create a function for everything. The problem is I can't pass task: URLSessionDataTask? as a parameter because it is a let constant. I understand the error Cannot assign to value: 'task' is a 'let' constant, but I can't figure out how to get around it because I have to cancel the task once prepareForReuse runs?

func setImageUsingURLSessionTask(photoUrlStr: String, imageView: UIImageView, task: URLSessionDataTask?)

    if let cachedImage = imageCache.object(forKey: photoUrlStr as AnyObject) as? UIImage {
        
        let resizedImage = funcToResizeImage(cachedImage)

        imageView.image = resizedImage
        return
    }

    guard let url = URL(string: photoUrlStr) else { return }

    task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

        // eventually resize image, set it to the imageView, and save it to cache
    })
    task?.resume()
}

Here's the cell if it's not clear. Once cellForItem runs and myObject gets initialized, I pass the photoUrlStr, imageView, and task, to the function. If the cell is scrolled off screen in prepareForReuse the task is cancelled so the incorrect image never appears. This works 100% fine if I set the URLSessionTask inside the cell itself instead of inside a function.

class MyCell: UICollectionViewCell {

    lazy var photoImageView: UIImageView = {
        // ...
    }()

    var task: URLSessionTask?

    var myObject: MyObject? {
        didSet {
            
            guard let photoUrlStr = myObject?.photoUrlStr else { return }

            setImageUsingURLSessionTask(photoUrlStr: photoUrlStr, imageView: photoImageView, task: task)
        }
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        
        task?.cancel()
        task = nil
        photoImageView.image = nil
    }
}

Upvotes: 0

Views: 264

Answers (1)

πter
πter

Reputation: 2217

You can pass your task as an inout parameter. A simplified version of your function would be:

func changeDataTask(inout task: URLSessionDataTask) {
    task = // You can change it
}

The variable what you pass to the function has to be var. You would call it like this:

var task = // Declare your initial datatask
changeDataTask(task: &task)

Upvotes: 1

Related Questions