如何将 URLSessionTask 作为参数传递

How to pass URLSessionTask as a parameter

我有一个单元格,我在其中使用 URLSessionTask 来获取一些图像。当单元格滚出屏幕时,在 prepareForReuse 中我取消了任务,一切正常。因为一旦我从任务中获得图像,我就会对图像做几件事,所以我想为所有内容创建一个函数。问题是我无法将 task: URLSessionDataTask? 作为参数传递,因为它是 let constant。我理解错误 Cannot assign to value: 'task' is a 'let' constant,但我不知道如何解决它,因为我必须取消prepareForReuse 运行后的任务?

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()
}

这里是单元格,如果不清楚的话。一旦 cellForItem 运行并且 myObject 被初始化,我将 photoUrlStr、imageView 和任务传递给该函数。如果单元格在 prepareForReuse 中滚出屏幕,任务将被取消,因此错误的图像永远不会出现。如果我在单元格本身而不是函数内部设置 URLSessionTask,这 100% 可以正常工作。

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
    }
}

您可以将任务作为 inout 参数传递。您的函数的简化版本是:

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

传递给函数的变量必须是var。你可以这样称呼它:

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