YeahGarage
@YeahGarage
Developer

Как правильно реализовать градиент в tableview cell?

Друзья, подскажите, как правильно реализовать градиент в ячейки, поскольку при текущей реализации и большой таблице видно некоторое замеделение
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
    }
  • Вопрос задан
  • 741 просмотр
Решения вопроса 1
doublench21
@doublench21 Куратор тега Swift
При всём моём к вам уважении, у меня глаза из орбит вылезли.

В свой день рождения я не буду ругаться, а постараюсь задать вам вопросы для более ясной картины. И так:

1) В курсе ли вы как работает жизненный цикл ячеек таблицы/коллекции? Судя по коду, предположу, что есть небольшие непонятки.

2) Работа с асинхронностью в данном контексте тоже абсолютно бесполезна. Вы просто тратите время на переключения контекста.
Помню вы хотели начать изучать асинхронность. Начали, но есть снова непонятки? Судя по коду.

Ответьте на эти вопросы и далее мы затронем сам градиент.

Эти два вопроса так же прилично тормозят ваш код.

Ответы получены. Двигаемся дальше.

1) Представьте себе что у вас ячейки высотой в 100, а вся таблица высотой в 500. Получаем 5 видимых ячеек. Таблица крайне экономно использует память телефона и на самом деле инстанцирует примерно видимое количество ячеек плюс 1-2 про запас для плавной прокрутки. Итого мы имеем 7 ячеек, которые вне зависимости сколько вы прописываете в дата соурс , будь то 50, использоваться для всех 50 будут лишь эти 7.

Метод же cellForItem вызывается для всех ячеек которые должны появиться. То есть это больше видимых снова и снова при скролле. То есть очень часто и много.

Этот метод должен быть настолько быстрым насколько это возможно и должен быть практически чистым от лишнего кода.

Надеюсь теперь ясно что глаза из орбит вылезли не зря, глядя на то, что сделали Вас.

Выводы.

Так как таблица будет использовать лишь 7 наших инстанцов, лучшим вариантом будет перенести создание градиента внутрь самой ячейки. Градиент будет создаваться внутри инициализатора ячейки.

А ваш код создаёт градиенты каждый раз как ячейка переиспользуется. Это как пытаться забить гвоздь в то место, где он уже есть.

2) Асинхронность нужно использовать для затратных по времени операций. Достать значения из массива такой очевидно не является. Асинхронно нужно получать данные. В вашем случае, всю асинхронность уберите полностью.

3) Уберите весь код по обновлению данных ячейки внутрь самой ячейки. Создайте метод, скажем func configure(...) и вызывайте аккуратно в методе cellForItem.

4) Попробуйте выставить градиенту(слою) св-во shouldRasterize в true. При этом так же добавьте rasterizationScale = UIScreen.main.scale
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы