Charts
Charts copied to clipboard
Crash building iterator. Range requires lowerBound <= upperBound
- [ x] I've read, understood, and done my best to follow the *CONTRIBUTING guidelines.
What did you do?
Upgrade from 3.6.0 to 4.0.2
What happened ?
Most drawing of charts leads to a crash when building iterator in
extension BarLineScatterCandleBubbleRenderer.XBounds: Sequence
because Range requires lowerBound <= upperBound
let entryTo = dataSet.entryForXValue(high, closestToY: .nan, rounding: .up)
is nil. It looks like the closest found is < endIndex in the dataset.
I use custom minimum and maximum axis values and visible range.
The same code was working perfectly in v3.6. I also tried to rollback to 3.6 as a temporary workaround but the project doesn't compile anymore with XCode 13.3.
Charts Environment
Charts version/Branch/Commit Number: 4.0.2 Xcode version: 13.3 (13E113) Swift version: 5 Platform(s) running Charts: iOS macOS version running Xcode: 12.0.1 (21A559)
Some problem

This can happen when max values are 0 or negative values. make sure the x values are not 0 or negative in the data entry x value array you add to the Chart Data entry. you can add a guard let to check if the max > min then proceed with make iterator as a temporary solution
hello @k1ran-ak, I just checked and I don't have any negative value in my data :
Charts.ChartDataSet Charts.ChartDataSet
Charts.ChartBaseDataSet Charts.ChartBaseDataSet
entries [Charts.ChartDataEntry] 60 values
_yMax Double 80.135000000000005
_yMin Double 49.600000000000001
_xMax Double 17737.416666666668
_xMin Double 16777.458333333332
Tried to swap min and max before building iterator if min > max and I got the chart display without a crash but when I scroll to the very end of it, the line disappear.
Found a quick fix (available in above pull request) that is not perfect and doesn't solve the source of the issue but at least it doesn't crash anymore
Hi @sebastienhannay. can you provide your 60 ChartDataEntry values? so I get more information about the crash.
Make sure you use x values are index. You can later change X values with value formatter.
Example: for index in 0..<high.count { let dataEntry = CandleChartDataEntry(x:Double(index) , shadowH: high, shadowL: low, open: open, close: close) candledataEntries.append(dataEntry) }
We are building a timeline so x values are a function on timeIntervalSince1970
(and so distance between 2 points may vary a lot depending on data that we have). We already use value formatter (calculation on timeIntervalSince1970
was to avoid huge values but it will be difficult to reduce more than that as the timeline may be quite long)
Here are my 60 values that cause the crash :
▿ 0 : ChartDataEntry, x: 16777.458333333332, y 78.546
▿ 1 : ChartDataEntry, x: 16782.458333333332, y 79.335
▿ 2 : ChartDataEntry, x: 16796.458333333332, y 78.836
▿ 3 : ChartDataEntry, x: 16804.458333333332, y 78.652
▿ 4 : ChartDataEntry, x: 16812.458333333332, y 78.523
▿ 5 : ChartDataEntry, x: 16813.458333333332, y 78.591
▿ 6 : ChartDataEntry, x: 16818.458333333332, y 78.976
▿ 7 : ChartDataEntry, x: 16821.458333333332, y 78.228
▿ 8 : ChartDataEntry, x: 16830.458333333332, y 79.165
▿ 9 : ChartDataEntry, x: 16838.458333333332, y 79.55
▿ 10 : ChartDataEntry, x: 16840.458333333332, y 78.473
▿ 11 : ChartDataEntry, x: 16841.458333333332, y 79.062
▿ 12 : ChartDataEntry, x: 16842.458333333332, y 78.668
▿ 13 : ChartDataEntry, x: 16855.458333333332, y 80.135
▿ 14 : ChartDataEntry, x: 16889.416666666668, y 78.914
▿ 15 : ChartDataEntry, x: 16895.416666666668, y 78.829
▿ 16 : ChartDataEntry, x: 16903.416666666668, y 79.331
▿ 17 : ChartDataEntry, x: 16909.416666666668, y 79.175
▿ 18 : ChartDataEntry, x: 16915.416666666668, y 78.453
▿ 19 : ChartDataEntry, x: 16921.416666666668, y 79.129
▿ 20 : ChartDataEntry, x: 16923.416666666668, y 78.438
▿ 21 : ChartDataEntry, x: 16926.416666666668, y 78.309
▿ 22 : ChartDataEntry, x: 16931.416666666668, y 78.263
▿ 23 : ChartDataEntry, x: 16932.416666666668, y 78.858
▿ 24 : ChartDataEntry, x: 16935.416666666668, y 79.253
▿ 25 : ChartDataEntry, x: 16936.416666666668, y 78.571
▿ 26 : ChartDataEntry, x: 16939.416666666668, y 79.557
▿ 27 : ChartDataEntry, x: 16943.416666666668, y 78.748
▿ 28 : ChartDataEntry, x: 16950.416666666668, y 78.992
▿ 29 : ChartDataEntry, x: 16951.416666666668, y 78.624
▿ 30 : ChartDataEntry, x: 16953.416666666668, y 79.237
▿ 31 : ChartDataEntry, x: 16958.416666666668, y 78.7615
▿ 32 : ChartDataEntry, x: 16962.416666666668, y 78.832
▿ 33 : ChartDataEntry, x: 16968.416666666668, y 78.335
▿ 34 : ChartDataEntry, x: 16971.416666666668, y 78.099
▿ 35 : ChartDataEntry, x: 16982.416666666668, y 78.939
▿ 36 : ChartDataEntry, x: 16989.416666666668, y 78.634
▿ 37 : ChartDataEntry, x: 16990.416666666668, y 78.604
▿ 38 : ChartDataEntry, x: 16994.416666666668, y 78.796
▿ 39 : ChartDataEntry, x: 16997.416666666668, y 79.1465
▿ 40 : ChartDataEntry, x: 16998.416666666668, y 78.414
▿ 41 : ChartDataEntry, x: 17014.416666666668, y 79.58
▿ 42 : ChartDataEntry, x: 17018.416666666668, y 78.153
▿ 43 : ChartDataEntry, x: 17021.416666666668, y 78.876
▿ 44 : ChartDataEntry, x: 17025.416666666668, y 77.746
▿ 45 : ChartDataEntry, x: 17029.416666666668, y 78.315
▿ 46 : ChartDataEntry, x: 17031.416666666668, y 78.468
▿ 47 : ChartDataEntry, x: 17033.416666666668, y 62.72666666666667
▿ 48 : ChartDataEntry, x: 17203.458333333332, y 75.0
▿ 49 : ChartDataEntry, x: 17543.458333333332, y 79.0
▿ 50 : ChartDataEntry, x: 17546.458333333332, y 80.0
▿ 51 : ChartDataEntry, x: 17549.458333333332, y 78.0
▿ 52 : ChartDataEntry, x: 17670.416666666668, y 49.8
▿ 53 : ChartDataEntry, x: 17672.416666666668, y 49.6
▿ 54 : ChartDataEntry, x: 17675.416666666668, y 50.5
▿ 55 : ChartDataEntry, x: 17677.416666666668, y 51.0
▿ 56 : ChartDataEntry, x: 17734.416666666668, y 53.0
▿ 57 : ChartDataEntry, x: 17735.416666666668, y 51.0
▿ 58 : ChartDataEntry, x: 17736.416666666668, y 50.0
▿ 59 : ChartDataEntry, x: 17737.416666666668, y 51.0
okay values seems to be fine. Do you have any X offset or Y offset assigned to your chart view ?
if you have any offset values try this
fileprivate init(min: Int, max: Int) { self.iterator = max >= min ? (min...max).makeIterator() : (min...min+50).makeIterator() }
50 - is your range given in setVisibleXRange(minXRange: 1, maxXRange: 50)
I have offset on X and also custom min and max values on both X and Y (add some padding to the charts so it matches our requirements). I can scroll in the chart horizontally but cannot zoom in or zoom out.
I just noticed that the crash happens when the scroll reach the very last point of the dataset (didn't notice earlier as I was automatically scrolling to the end on display) so maybe it is related to the dataset or custom viewing window.
Tried your solution, it prevent the crash but as soon as the last point is displayed, the line disappear but i still have the datapoints
I can scroll in the chart horizontally but cannot zoom in or zoom out -> for this issue check if the scaleY is enabled and pinchZoom enabled
Can you share all of your offset codes along with the offset values
I can scroll in the chart horizontally but cannot zoom in or zoom out This is not an issue, this is how I set it in my chart, mentioned it just in case it could help.
About the offset, I tried to isolate the issue as much as possible and it looks like setting any xAxis.axisMaximum
bigger than data.xMax
will make it crash as soon as we reach the end of the chart. Looks like setting it to something lower will not make it crash as we can't reach the end of the chart but it mess up the display.
For the data that I shared, I set xAxis.axisMaximum = 17742.41665509259
but I tried 17738
(round up of data.xMax
) and 17737
(round down of data.xMax
) and both had bad behavior
For the data that I shared, I set
xAxis.axisMaximum = 17742.41665509259
but I tried17738
(round up ofdata.xMax
) and17737
(round down ofdata.xMax
) and both had bad behavior
setting xAxis.axisMaximum will force the chart to stop at that particular value.Check if you have same functionality without setting axisMaximum.
Yes it works correctly when I don't set axisMaximum so it can be a quick fix but it will have some differences in the display. In my case setting an axisMaximum adds some padding in the chart. The charts frame shows data by week and the axis maximum is set to display the full week even on the very last week. So if my last data value is on Tuesday, it extends the chart to Sunday. It gives a better UI so it would be a shame to lose it... And It still works perfectly on axisMinimum
Seems like the issue is when you try to find the closest point to the max.
The comparison seems to be : var closest = partitioningIndex { $0.x >= xValue }
which is not really the closest but the closest after specific xValue.
In my case closest x is lower than xValue as I don't have any point >= axisMaximum
Seems like the issue is when you try to find the closest point to the max.
The comparison seems to be :
var closest = partitioningIndex { $0.x >= xValue }
which is not really the closest but the closest after specific xValue. In my case closest x is lower than xValue as I don't have any point >= axisMaximum
Yeah I think you are using x values in Data Entry as timestamps instead you can try to use the index of the loop in which you append the values as x values. then use value formatter to IndexAxisFormatter and give your timestamps
And then you can set Axis Maximum. Lets say I have total of 60 values my Axis Maximum would be 70 and I should manually add the timestamps for the 10 extra points that's needed to be shown in the graph(I'm not sure about this part)
In case if you are not using timestamps as x values To achieve a padding you need to assign x offset(while assigning don't give it more than the x axis range you have assigned).
They are not directly timestamps but derive of timestamps. The problem is that I don't have values for every day and can't add extra points to my chart without losing its accuracy. I need a scale that represent a real time scale and all points that are on my chart should be associated with a value added by the user. So your solution doesn't seems to fit my needs...
Correct me if I'm wrong but if I use xOffset instead of xAxis.axisMaximum I will get the same padding at the beginning and end of the chart which, again, doesn't really fit my needs.
Correct me if I'm wrong but if I use xOffset instead of xAxis.axisMaximum I will get the same padding at the beginning and end of the chart which, again, doesn't really fit my needs.
Yes you will get at both ends but you can move your chart view to last xValue with moveViewToX which displays your chart view's last x point with padding on right side alone , unless user decides to scroll to very first value.
I see, could also be a quick fix but it's it would be better if could work the same way as in v3.6. Looks like this version bring more limitations than the previous one... I saw a branch that restore the old way of calculating xbounds (https://github.com/danielgindi/Charts/tree/bugfix/xbounds-iterator) that may fix my issue but I don't know if it limits some newer features. Would be awesome if I could have the same display as before without adding some tricks in the code to compensate what seems to be a regression.
I see, could also be a quick fix but it's it would be better if could work the same way as in v3.6. Looks like this version bring more limitations than the previous one... I saw a branch that restore the old way of calculating xbounds (https://github.com/danielgindi/Charts/tree/bugfix/xbounds-iterator) that may fix my issue but I don't know if it limits some newer features. Would be awesome if I could have the same display as before without adding some tricks in the code to compensate what seems to be a regression.
The version of Charts you linked is of Version 4.0.0 I think you won't lose much on new features probably 4.0.2 have some bug fixes.
I mean as it roll back the new calculation of xbounds introduce in 4.0.0 to the one in 3.6. I guess there must be a reason why it changed that much between 3.6 and 4.0.x. Again this could probably solve my issue but it would probably be better to fix the new calculation method than rollback to the old one
I am also seeing this in version 4.0.2. When I set a maximum value on the x axis, I get a sporadic crash, and the line disappears when I zoom out all the way.
I am also seeing this in version 4.0.2. When I set a maximum value on the x axis, I get a sporadic crash, and the line disappears when I zoom out all the way.
Did you set visibleXRange ?
No, will that help? It seems to automatically limit the zoom so I can't zoom out past the extent of the data. (Just to clarify my last post, the line disappears when I zoom out so all the data points are visible; I don't need to zoom out a crazy amount.)
No, will that help? It seems to automatically limit the zoom so I can't zoom out past the extent of the data. (Just to clarify my last post, the line disappears when I zoom out so all the data points are visible; I don't need to zoom out a crazy amount.)
In case if you don't want to scale a crazy amount you can set maximum scale limit with
if barChartView.scaleX > 1.3
{
barChartView.notifyDataSetChanged()
barChartView.scaleXEnabled = false
}
Change 1.3 to match whatever zoom level you wanted to limit it.
I'm also seeing this issue. I'm using time interval since 1970 as x values and drawing a CombinedChartView
with candlesticks, line and bar data. Not sure if this helps, but it seems like the crash occurs when there is a big gap between 2 entries and the user tries to pan the view to show this part.
I'm also seeing this issue. I'm using time interval since 1970 as x values and drawing a
CombinedChartView
with candlesticks, line and bar data. Not sure if this helps, but it seems like the crash occurs when there is a big gap between 2 entries and the user tries to pan the view to show this part.
@PWrzesinski Yes charts will not function properly when time stamps are used. You can make use of indexes instead of timestamps and change the x axis values later with Axis Formatter Class. Like this https://github.com/danielgindi/Charts/issues/4798#issuecomment-1090169068
I'm also seeing this issue. I'm using time interval since 1970 as x values and drawing a
CombinedChartView
with candlesticks, line and bar data. Not sure if this helps, but it seems like the crash occurs when there is a big gap between 2 entries and the user tries to pan the view to show this part.@PWrzesinski Yes charts will not function properly when time stamps are used. You can make use of indexes instead of timestamps and change the x axis values later with Axis Formatter Class. Like this #4798 (comment)
Thanks @k1ran-ak, I've reduced the numbers so instead of starting 1.01.1970 they will start with the lowest date from all values, so if my earliest data point is 1.01.2021 that will be value 0. This fixed the crash for me.
Still I must say, Charts is pretty close to working with dates since 1970, apart from this crash I've only encountered the issue with candlesticks being very thin which feels like it should be fixable. There is also one unrelated issue, but otherwise I'm super happy with the framework!
@PWrzesinski If you are using timestamps as X-axis values, you will be getting a thin candle stick chart as the difference between two consequetive timestamps is large. Thats why I earlier mentioned to use indices of the timestamps array ie. 0,1,2 .... and later change the x axis labels with Axis formatter class. If you want me to explain in detail I can do it so let me know if there is anything I could do to help you.
@PWrzesinski If you are using timestamps as X-axis values, you will be getting a thin candle stick chart as the difference between two consequetive timestamps is large. Thats why I earlier mentioned to use indices of the timestamps array ie. 0,1,2 .... and later change the x axis labels with Axis formatter class. If you want me to explain in detail I can do it so let me know if there is anything I could do to help you.
Thank you, I appreciate the help! There are a few reasons I'd like to avoid using the index approach you're suggesting, but your comment clarified for me why the candlesticks are so thin. In the end I simply divided the timestamps by 10 after offsetting them to the start date and now they look good. Thanks! 😅
@PWrzesinski Glad I could be of any help 😊.