在异步加载上为cell.image查看动画

时间:2017-08-01 10:31:32

标签: ios swift animation race-condition

我试图做一个表格,当图像完成加载(异步)时,单元格上的imageView将alpha从0更改为1。 我做了什么似乎只是在一个图像显示而不是淡入。我确定这是一种竞争条件但我不熟悉iOS中的动画并且不知道如何解决这个问题。任何输入都会很棒。 这是我的代码:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    //Configure the cell...
    let episode = episodes[indexPath.row]

    cell.textLabel?.text = episode.title

    cell.detailTextLabel?.text = episode.content

    let logoUrl = URL(string: episode.logoUrl!)

    if (episode.logoImage == nil){
        episode.logoImage = UIImage()
        DispatchQueue.global().async {
            let data = try? Data(contentsOf: logoUrl!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
            DispatchQueue.main.async {
                episode.logoImage = UIImage(data: data!)
                cell.imageView?.image = episode.logoImage
                self.episodesTable.reloadData()
                cell.imageView?.alpha = 0
                UIView.animate(withDuration: 1, animations: {
                    cell.imageView?.alpha = 1
                })

            }
        }
    } else{
        cell.imageView?.image = episode.logoImage
    }

    return cell
}

2 个答案:

答案 0 :(得分:3)

在动画设置为1之前,您需要先将alpha设置为0.

cell.imageView?.alpha = 0
UIView.animate(withDuration: 1, animations: {
                    cell.imageView?.alpha = 1
                })

此外,您不需要重新加载表。删除self.episodesTable.reloadData()

您正在跨越后台线程并从该线程内的url加载图像。如果在用户之间滚动单元格,该怎么办?你会在错误的单元格上留下错误的图像(因为细胞重用,就是这样)。

我的建议是使用SDWebImageCache,并使用其完成块为alpha设置动画。

// Changing animation duration to 0.2 seconds from 1 second 
if(cacheType == SDImageCacheTypeNone) {
    cell.imageView?.alpha = 0
    [UIView animateWithDuration:0.2 animations:^{ 
        cell.imageView?.alpha = 1;
    }];
}

答案 1 :(得分:1)

reloadData()调用导致重新加载所有单元格,包括您尝试设置动画的单元格。我的建议是用它的索引路径标记你的单元格。在异步调用之后检查它是否仍然呈现正确的数据并在不重新加载整个表视图的情况下为其设置动画。

// ...
cell.tag = indexPath.item
DispatchQueue.global().async {
    // async load
    DispatchQueue.main.async {
        guard cell.tag == indexPath.item else { return }
        cell.imageView?.alpha = 0.0
        cell.imageView?.image = image
        // animate
    }
}
// ...