D
D
Dima Grib2019-04-21 16:20:20
Swift
Dima Grib, 2019-04-21 16:20:20

How to properly implement gradient in tableview cell?

Friends, tell me how to correctly implement the gradient into cells, because with the current implementation and a large table, some slowdown is visible

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! FeedTableViewCell
        dispQueueGlobUtility.async {
            var title = self.userNameArray[indexPath.row]
            title.capitalizeFirstLetter()
            let url = URL(string: self.proPicUrlArray[indexPath.row])
            let id = self.userIdArray[indexPath.row]
            DispatchQueue.main.async {
                cell.userName.text = title
                cell.profileImageView.sd_setImage(with: url, completed: nil)
                cell.profileImageView.contentMode = .scaleAspectFill 
                cell.userId.text = id
                cell.userPic = self.proPicUrlArray[indexPath.row]
                let gradientLayer: CAGradientLayer = CAGradientLayer()
                let shapeLayer = CAShapeLayer()
                let startColor: UIColor = UIColor(red: 0.78, green: 0.18, blue: 0.56, alpha: 1.0)
                let endColor:   UIColor = UIColor(red: 0.98, green: 0.62, blue: 0.30, alpha: 1.0)
                let gradientColors: [CGColor] = [startColor.cgColor, endColor.cgColor]
                gradientLayer.calculatePoints(for: 110)
                gradientLayer.frame = CGRect(x: -0.1, y: 0, width: cell.profileImageView.frame.width, height: cell.profileImageView.frame.height)
                gradientLayer.colors = gradientColors
                let lineWidth: CGFloat = 2
                let maskPath = UIBezierPath(roundedRect:  cell.profileImageView.bounds.insetBy(dx: lineWidth/2, dy: lineWidth/2), byRoundingCorners: [.allCorners], cornerRadii: CGSize(width: cell.profileImageView.frame.width/2, height: cell.profileImageView.frame.height/2)).cgPath
                shapeLayer.lineWidth = 2
                shapeLayer.path = maskPath
                shapeLayer.strokeColor = UIColor.black.cgColor
                shapeLayer.fillColor = UIColor.clear.cgColor
                gradientLayer.mask = shapeLayer
                cell.profileImageView.layer.insertSublayer(gradientLayer, at: 1)
            }
        }
        return cell
    }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
doublench21, 2019-04-21
@YeahGarage

With all due respect to you, my eyes popped out of their sockets.
On my birthday, I will not swear, but I will try to ask you questions for a clearer picture. And so:
1) Do you know how the life cycle of table/collection cells works? Judging by the code, I assume that there are small misunderstandings.
2) Working with asynchrony in this context is also absolutely useless. You are just wasting time on context switches.
I remember you wanted to start learning about asynchrony. We started, but there are still misunderstandings? According to the code.
Answer these questions and then we will touch on the gradient itself.
These two questions slow down your code as well.
Answers received. We move on.
1) Imagine that you have cells 100 high, and the entire table is 500 high. We get 5 visible cells. The table uses the phone's memory extremely economically and actually instantiates approximately the visible number of cells, plus 1-2 in reserve for smooth scrolling. In total, we have 7 cells, which, regardless of how much you write in the date source, be it 50, only these 7 will be used for all 50.
The cellForItem method is called for all cells that should appear. That is, it is more visible over and over again when scrolling. That is, very often and a lot.
This method should be as fast as possible and should be practically code-free.
I hope now it is clear that the eyes popped out of their sockets not in vain, looking at what you did.
Findings.
Since the table will only use 7 of our instances, the best option would be to move the creation of the gradient inside the cell itself. The gradient will be created inside the cell initializer.
And your code creates gradients every time a cell is reused. It's like trying to hammer a nail into a place where it already exists.
2) Asynchrony should be used for time-consuming operations. Getting values ​​from an array is obviously not such a thing. Asynchronously it is necessary to receive the data. In your case, remove all asynchrony completely.
3) Remove all the code for updating cell data inside the cell itself. Create a method, say func configure(...) and call it carefully in the cellForItem method.
4) Try setting the gradient(layer) shouldRasterize property to true. In doing so, also add rasterizationScale = UIScreen.main.scale

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question