我创建了一个折线CAShapeLayer
图MTKView
。在某些情况下,此折线图每秒更新一次,但在当前的实现中,每当图表更新(每秒)时,都会有一个微小的冻结时刻,因为它会再次绘制所有内容。我尝试了我能想到的一切来提高它的性能,但我无法修复它。当新数据到来时,这个冻结时刻不允许图表平稳移动。
这是我的代码的一部分:
class LineChartView: MTKView, UIScrollViewDelegate {
private let scrollView: UIScrollView = UIScrollView()
public var lineGap: CGFloat = 0.7
var dataEntries: [PointEntry]? {
didSet {
DispatchQueue.main.async {
self.setNeedsLayout()
}
}
}
private var hrDataPoints: [CGPoint]?
override func layoutSubviews() {
if let dataEntries = dataEntries {
scrollView.frame = CGRect(x: 50, y: 0, width: frame.size.width, height: frame.size.height)
scrollView.contentSize = CGSize(width: 50 + CGFloat(dataEntries.count) * lineGap, height: frame.size.height)
mainLayer.frame = CGRect(x: 0, y: 0, width: CGFloat(dataEntries.count) * lineGap, height: frame.size.height)
dataLayer.frame = CGRect(x: 0, y: topSpace, width: mainLayer.frame.width, height: mainLayer.frame.height - topSpace - bottomSpace)
hrDataPoints = convertDataEntriesToPoints(entries: dataEntries)
clean()
drawCharts()
}
}
}
// MARK: - Drawing
extension LineChartView {
private func convertDataEntriesToPoints(entries: [PointEntry]) -> [CGPoint] {
if let max = entries.max()?.value, let min = entries.min()?.value {
let filteredMax = max + emptySpaceAboveAndBelowChart
let filteredMin = min - emptySpaceAboveAndBelowChart
var result: [CGPoint] = []
let minMaxRange: CGFloat = CGFloat(filteredMax - filteredMin) * topHorizontalLine
for i in 0 ..< entries.count {
let height = dataLayer.frame.height * (1 - ((CGFloat(entries[i].value) - CGFloat(filteredMin)) / minMaxRange))
let point = CGPoint(x: CGFloat(i) * lineGap + 40, y: height)
result.append(point)
}
return result
}
return []
}
private func drawCharts() {
let lineLayer = CAShapeLayer()
lineLayer.lineWidth = 2
lineLayer.fillColor = UIColor.clear.cgColor
guard let path = createPath() else { return }
lineLayer.path = path.cgPath
lineLayer.strokeColor = UIColor.green.cgColor
lineLayer.drawsAsynchronously = true
dataLayer.addSublayer(lineLayer)
}
private func createPath() -> UIBezierPath? {
var dataPoints: [CGPoint] = []
guard let points = hrDataPoints, points.count > 0 else { return nil }
dataPoints = points
let path = UIBezierPath()
path.move(to: dataPoints[0])
for i in 1 ..< dataPoints.count {
path.addLine(to: dataPoints[i])
}
return path
}
}
// MARK: - Cleaning
extension LineChartView {
private func clean() {
mainLayer.sublayers?.forEach({
if $0 is CATextLayer {
$0.removeFromSuperlayer()
}
})
gridLayer.sublayers?.forEach({ $0.removeFromSuperlayer() })
dataLayer.sublayers?.forEach({ $0.removeFromSuperlayer() })
}
}
并且在新数据到来的每一秒,新数据都会被追加到dataEntries
. 如果有人可以在这里给我一些建议,我将不胜感激。
谢谢