[ios] Skip excessive elevation point updates

When the user drags the elevation chart it runs chart's `selected point` update mechanism by calling the `onSelectedPointChanged` inside the `ChartView`'s ` func chartPreviewView(_ view: ChartPreviewView, didChangeMinX minX: Int, maxX: Int)`. This updates may be quite often (tens/hundreds per sec) and may cause the `on point update` callback **recursion** and overloads the `layoutSubviews` method on the _short track_ because the ChartView doesnt have mechanism to skip excessive updates when the parameters the same.
This situation produces fail with internal error `(null) in -[NSISEngine _flushPendingRemovals] ().`

The fix include:
1. skip updates when the current point isn't changed
2. remove layoutSubviews overloading (this method should recalc the layout immediately and should not be called too frequent, the `setNeedsLayout` allows to batch the layout updates and redraw the view on the next runtime cycle)

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
Kiryl Kaveryn
2025-08-18 13:07:15 +04:00
committed by Yannik Bloscheck
parent 31970c87c4
commit d94351a8f1
2 changed files with 4 additions and 1 deletions

View File

@@ -94,7 +94,7 @@ final class ChartPointInfoView: UIView {
func update(x: CGFloat, label: String, points: [ChartLineInfo]) {
distanceLabel.text = label
altitudeLabel.text = altitudeText(points[0])
layoutIfNeeded()
setNeedsLayout()
}
private func altitudeText(_ point: ChartLineInfo) -> String {

View File

@@ -16,6 +16,7 @@ public class ChartView: UIView {
var showPreview: Bool = false // Set true to show the preview
private var tapGR: UITapGestureRecognizer!
private var selectedPointDistance: Double = 0
private var panStartPoint = 0
private var panGR: UIPanGestureRecognizer!
private var pinchStartLower = 0
@@ -170,6 +171,8 @@ public class ChartView: UIView {
}
public func setSelectedPoint(_ x: Double) {
guard selectedPointDistance != x else { return }
selectedPointDistance = x
let routeLength = chartData.xAxisValueAt(CGFloat(chartData.pointsCount - 1))
let upper = chartData.xAxisValueAt(CGFloat(chartPreviewView.maxX))
var lower = chartData.xAxisValueAt(CGFloat(chartPreviewView.minX))