在异步加载时设置动画 cell.imageview

Animate cell.imageview on async load

我正在尝试做一个 table,当图像完成加载(异步)时,单元格上的 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
}

您需要先将 alpha 设置为 0,然后再设置为 1。

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

此外,您不需要重新加载 table。删除 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;
    }];
}

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

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