加载图像异步并返回UIImage的公共函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加载图像异步并返回UIImage的公共函数相关的知识,希望对你有一定的参考价值。

我正在尝试编写加载图像异步并返回UIImage的公共函数。我想用它来填充UITableView图像。

class CommonFunctions {

func loadImageAsync(StringURL: NSString) -> UIImage{

    var returningImage = UIImage()

    let url = NSURL(string: StringURL)

    let requestedURL = NSURLRequest(URL: url!)

    NSURLConnection.sendAsynchronousRequest(requestedURL, queue: NSOperationQueue.mainQueue(), completionHandler: {
        response, data, error in

        if error != nil {
            println("there is some error loading image")
        }
        else {

            if let image = UIImage(data: data){
                returningImage = image
            }
        }
    })
    return returningImage
    }

}

问题是,当我想使用这个功能时:

cell.imageModelImage.image = CommonFunctions.loadImageAsync(CommonFunctions)

而不是String参数我得到了这个类?为什么会这样?

答案

你问:

而不是String参数我得到了这个类?为什么会这样?

这是因为你正在调用它,好像它是一个类函数,但没有这样定义它。如果在函数声明中添加class关键字,则不会看到该行为。

但是这里存在更深层次的问题:您无法从异步函数返回值(因为该函数将立即返回,而异步请求将在稍后完成)。

一种解决方案是提供一个完成处理程序,如果成功检索到图像,将会调用该处理程序:

class func loadImageAsync(stringURL: String, completion: @escaping (UIImage?, Error?) -> Void) {
    let url = URL(string: stringURL)!

    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else {
            DispatchQueue.main.async { completion(nil, error) }
            return
        }
        let image = UIImage(data: data)
        DispatchQueue.main.async { completion(image, nil) }
    }.resume()
}

注意,我正在将完成处理程序分派回主队列,在那里应该进行所有UI更新。

然后,在tableView(_:cellForRowAt:)中,您可以提供在异步请求完成时将调用的块:

cell.imageModelImage.image = ... // remember to initialize image view before starting async method
CommonFunctions.loadImageAsync(with: "http://example.com/test.jpg") { image, error in
    if let cell = tableView.cellForRow(at: indexPath) as? CustomCell {  // make sure cell hasn't scrolled out of view
        cell.imageModelImage.image = image
    }
}

注意,上面假设在中间时间段内不可能在表格中插入一行。如果该假设无效,而不是使用旧的indexPath,则可能需要重新查询模型以确定在调用异步完成处理程序时IndexPath对此单元格有效。

对于Swift 2的演绎,请参阅此答案的previous revision

以上是关于加载图像异步并返回UIImage的公共函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥所有异步图像加载(SDWebImage、AFNetworking)库都使用 UIImageView 而不是 UIImage?

UIImage initWithData:从异步调度中阻塞 UI 线程?

如何处理 NSData 并返回 UIImage (Swift)

防止 UITableViewCell 的 UIImageView 调整异步加载的 UIImage 的大小

UITableView 中的 UIImage 显示另一个单元格的图像一秒钟

当片段视图加载是异步任务的一部分时,如何在片段加载之前显示进度条?