Warm tip: This article is reproduced from serverfault.com, please click

Cached shadow path for UITableView

发布于 2020-11-27 19:14:33

I want to cache a shadow path to make the performance of UITableView better.

I've read https://yalantis.com/blog/mastering-uikit-performance/ that

if let rect = cell.imageView?.bounds {
    cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}

would stop offscreen shadows, however using the following function

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "Cell data: \(data[indexPath.row])"
        
        if let rect = cell.imageView?.bounds {
          cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
        }
        
        cell.imageView?.layer.shadowRadius = 8
        cell.imageView?.layer.shadowOffset = CGSize(width: 3, height: 3)
        cell.imageView?.layer.shadowOpacity = 0.5
        
        
        cell.imageView?.layer.cornerRadius = 20
        cell.imageView?.image = UIImage(named: "PlaceholderImage")
        return cell
    }

produces a result where some cells have the shadow and some don't.

enter image description here

How can I implement caching of shadow paths to all cells in a simple UITableView

Questioner
WishIHadThreeGuns
Viewed
0
matt 2020-11-28 09:56:14

The problem is these lines:

    if let rect = cell.imageView?.bounds {
        cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
    }

If the cell's imageView has never been assigned an image, its frame is .zero and so its bounds is .zero. So the shadowPath ends up with a cgPath that is just a point, and no shadow appears.

The way I would solve this is that I would not use the built-in imageView property at all. I'd use a custom cell class with my own image view whose frame I can control, instead of the built-in imageView which plays these sorts of tricks.