#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 ()» из самой ячейки, это идеально!!