Нарисованный круг, дважды появляющийся в ячейках моего табличного представления в swift

#ios #swift #tableview #cell

#iOS #swift #просмотр таблицы #ячейка

Вопрос:

В моей ячейке tableview я рисую круг, который представляет процент правильных ответов, но я не знаю почему, этот круг появляется дважды только на некоторых устройствах (например, iPhone SE 1-го поколения или iPhone 12 Pro max).

Я не думаю, что это происходит из повторно используемой ячейки, потому что она поступает напрямую без какой-либо прокрутки.

Обратите внимание, что я использовал тот же метод для рисования того же круга в другом месте приложения, он работает отлично.

Я глубоко искал в своем коде, я вызываю этот метод только один раз для ячейки, поэтому я пришел к выводу, что это ошибка… Я немного потерялся здесь, я чувствую, что мой код в порядке, поэтому, я думаю, я больше ищу подсказку, чтобы избавиться от этого второго круга.

Класс для моих методов процентного круга :

 class PercentageCircle{
// Pattern singleton
public static let percentageCircle = PercentageCircle()



// Public init for pattern singleton
public init() {}

// Method to create and animate percentage circle
func createPercentageCircle(percentage: Int,
                            circleRadius: CGFloat,
                            circleXPosition: CGFloat,
                            circleYPosition: CGFloat,
                            circleWidth: CGFloat,
                            circleColor: CGColor,
                            backgroundColor: CGColor,
                            animation: Bool) -> UIView? {
    
    // Percentage circle to be animated
    let percentageCircle = CAShapeLayer()
    
    // Add a view
    let roundView = UIView(frame:CGRect(x: circleXPosition, y: circleYPosition, width: circleRadius, height: circleRadius))
    
    // Start of the arc corresponds to 12 0'clock
    let startAngle = -CGFloat.pi / 2
    // Proportion depending of percentage
    let proportion = CGFloat(percentage)
    let centre = CGPoint (x: roundView.frame.size.width / 2, y: roundView.frame.size.height / 2)
    let radius = roundView.frame.size.width / 2
    // The proportion of a full circle
    let arc = CGFloat.pi * 2 * proportion / 100
    
    // Add the background circle
    let backgroundCircle = CAShapeLayer()
    // Add path for background circle
    let pathBackground = UIBezierPath(arcCenter: centre, radius: radius, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi , clockwise: true)
    // Attributes of the background circle
    backgroundCircle.strokeColor = backgroundColor
    backgroundCircle.lineWidth = circleWidth * 1.7
    // Put transparency to the center of the circles
    backgroundCircle.fillColor = UIColor.clear.cgColor
    // Atribute the path
    backgroundCircle.path = pathBackground.cgPath
    
    // Add the circle to the view
    roundView.layer.addSublayer(backgroundCircle)
    
    // Add the path of the percentage circle
    let circularPath = UIBezierPath(arcCenter: centre, radius: radius, startAngle: startAngle, endAngle: startAngle    arc, clockwise: true)
    
    // Attribute the path to the percentage circle
    percentageCircle.path = circularPath.cgPath
    
    // Attributes of the percentage circle
    percentageCircle.strokeColor = circleColor
    percentageCircle.lineWidth = circleWidth
    percentageCircle.lineCap = .round
    percentageCircle.fillColor = UIColor.clear.cgColor
    
    // Check if animation is true
    if animation {
        // Do not draw the circle
        percentageCircle.strokeEnd = 0.0
        // Draw the circle thru the animation
        animateCircle(percentageCircle: percentageCircle)
        // Add the circle to the the view
        roundView.layer.addSublayer(percentageCircle)
    } else {
        // Draw the circle
        percentageCircle.strokeEnd = 1.0
        // Add the circle to the the view
        roundView.layer.addSublayer(percentageCircle)
    }
    
    return roundView
}

// Method to animate the circle
private func animateCircle(percentageCircle: CAShapeLayer) {
    let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
    // Set the animation to the total value
    basicAnimation.toValue = 1
    // Set the time of the animation
    basicAnimation.duration = 1
    // Set the circle to stay once the animation is completed
    basicAnimation.fillMode = .forwards
    basicAnimation.isRemovedOnCompletion = false
    
    // Add the animation to the percentage circle
    percentageCircle.add(basicAnimation, forKey: "keyAnimation")
}
 

}

Код для моей ячейки

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "detailStatsCell", for: indexPath) as? StatsTableViewCell else {
        return UITableViewCell()
        }
    
    let kanjiCurrentKey = kanjiStatArray[indexPath.row]
    
    cell.kanjiLabel.text = kanjiStatArray[indexPath.row]
    
    cell.appearnceLabel.text = "Appearance : (Stats.stats.countKanjiQuizz[kanjiCurrentKey] ?? 0)"
    

    if let statCorrect = Stats.stats.countKanjiCorrect[kanjiCurrentKey] {
        // Calculate the percentage
        let percentageKanjiCell = Int(100 * Double(statCorrect) / Double(Stats.stats.countKanjiQuizz[kanjiCurrentKey] ?? 1))

        // Set the correct answers if more than 1
        cell.correctLabel.text = "Correct : (statCorrect)"

        // Set the correct percentage
        cell.percentageLabel.text = String(percentageKanjiCell)   " %"

        // Draw the circle with the percentage in it
        drawCircle(percentage: percentageKanjiCell, cell: cell)
    } else {
        // Set the correct answers to 0 and draw the circle at 0%
        cell.correctLabel.text = "Correct : 0"
        drawCircle(percentage: 0, cell: cell)
    }
    
    
    return cell
}

//MARK: Draw percentage circle with percentage label
private func drawCircle(percentage: Int, cell: StatsTableViewCell){
    // Calculate the circle radius
    var circleRadius: CGFloat {
        return cell.frame.height/2   10
    }
    
    // Calculate the x position of the percentage circle
    var circleXPosition: CGFloat {
        return cell.frame.width - (circleRadius) - 10
    }
    
    // Calculate the y position of the percentage circle
    var circleYPosition: CGFloat {
        return cell.frame.height/2 - (circleRadius/2)
    }
    


    // Call method from PercentageCircle class

    roundView = PercentageCircle.percentageCircle.createPercentageCircle(percentage: percentage, circleRadius: circleRadius, circleXPosition: circleXPosition, circleYPosition: circleYPosition, circleWidth: 5, circleColor: #colorLiteral(red: 0.276517272, green: 0.2243287563, blue: 0.4410637617, alpha: 1), backgroundColor: #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1), animation: false)
    
    cell.addSubview(roundView)
}
 

Так и должно быть (iPhone 12 mini)

Вот как это выглядит на некоторых устройствах (iPhone 12 Pro max)

Комментарии:

1. Ячейки используются повторно при прокрутке таблиц. На небольших устройствах прокрутка более вероятна. Вы добавляете вложенное представление при каждом cellForRow вызове. Не делайте этого. Создайте круговой вид один раз при создании ячейки и просто обновите ее значение в cellForRow

2. Большое спасибо Paulw11!! Я меняю местоположение метода, как вы предложили, и вызываю его в «переопределении функции prepareForReuse ()» из самой ячейки, это идеально!!