UITableView缓慢加载图像

UITableView缓慢加载图像,uitableview,swift,Uitableview,Swift,TableView从解析api获取图像。但是,当在tableView中滚动时,图像加载时会出现延迟 有没有有效的方法来减少滞后?在用户滚动到单元格之前或之后加载图像的方法?我不太熟悉处理异步调用 获取图像函数 TableView单元 您可以使用PFImageView免费获得此功能,只需编写较少的代码即可达到预期效果。只需在设置文件属性后调用loadInBackground即可 至于UI滞后,请在仪器中进行配置,以确定什么是如此昂贵,以至于导致显著滞后。一些想法: 您应该确认此完成块是否正在主线程

TableView从解析api获取图像。但是,当在tableView中滚动时,图像加载时会出现延迟

有没有有效的方法来减少滞后?在用户滚动到单元格之前或之后加载图像的方法?我不太熟悉处理异步调用

获取图像函数 TableView单元
您可以使用PFImageView免费获得此功能,只需编写较少的代码即可达到预期效果。只需在设置文件属性后调用loadInBackground即可

至于UI滞后,请在仪器中进行配置,以确定什么是如此昂贵,以至于导致显著滞后。

一些想法:

您应该确认此完成块是否正在主线程上运行,检查NSThread.isMainThread,如果没有,请确保将映像视图的更新发送回主线程,例如dispatch_asynchdispatch_get_main_queue{…}。尝试从后台线程执行UIKit控件的更新可能会导致不一致的行为,因此请确保仅从主线程更新UI

您应该考虑用户在表视图中快速向下滚动和后退的含义。您的代码将导致重新获取以前检索到的图像

有时,底层的NSURLCache会优雅地处理这个问题,为您缓存图像。在其他情况下,它不会。遗憾的是,网络请求的缓存是由一些相当不透明的标准决定的,并且取决于服务器实现,您可能无法对此进行太多控制

您可能希望确认您的行为,并实现自己的缓存,例如,对以前下载的图像进行NSCache,并在再次检索图像之前进行检查

我会确保与网络链接调节器一起测试此过程,以便您可以确认应用程序在不理想的环境中的行为,即现实世界中的情况

与您的问题无关,异步更新单元格有两个问题:

如果在图像检索完成时单元格已从视图中滚出,则该单元格可能已被重用,并且该单元格可能已被重新用于表中的另一行。通过使用网络链接调节器运行应用程序,将网络响应时间降低到更高的级别(例如,手机接口不良),来测试这一点。这个问题可以表现为图像的闪烁或用与其他细胞相关的图像替换图像

通常通过调用tableView.CellForRowatinedexpathIndexPath作为UITableView方法来解决此问题,不要与类似命名的UITableViewDataSource方法混淆,如果此索引路径已从屏幕上滚下,该方法将返回nil,如果单元格可见,则返回UITableViewCell。在进行单元格的最终异步填充时,使用此值,而不是以前建立的单元格值

如果表可能已被重新加载,即在异步检索图像的过程中数据源发生了更改,则您可能实际上希望返回到模型,确定与刚才异步下载的图像相关联的适当索引路径

总之,想象一些退化的情况,在那里花了一分钟左右的时间来检索图像,这是不可能的,想象一下。仔细考虑与单元格滚动并随后重新使用相关的意外情况,图像的indexPath可能不再有效,等等。。确保你优雅地处理这些突发事件

func fetchImage(restaurantArray: PFObject!, completionHandler: ImageCompletionHandler!){
    var imageReference = restaurantArray["PhotoUploaded"] as PFFile
    imageReference.getDataInBackgroundWithBlock{
        (data, error) -> Void in

        if (error != nil){
            completionHandler(image: nil, error: error)
        }else{
            let image = UIImage(data: data)
            completionHandler(image: image, error: nil)
        }
    }
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("RestaurantCell", forIndexPath: indexPath) as FeedCell

    cell.nameLabel.text = restaurantNames[indexPath.row]

    // check if image is empty
    if foodPhotoObjects.isEmpty {
    } else {

        self.fetchImage(self.foodPhotoObjects[indexPath.row] as? PFObject, completionHandler: {
            (image, error) -> () in
            if image != nil {
                cell.mainRestaurantImageView.image = image
                cell.mainRestaurantImageView.contentMode = .ScaleAspectFill
                cell.mainRestaurantImageView.clipsToBounds = true
            }else{
                //alert user: no image or put placeholder image
            }
        })
    }

    return cell
}