Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

notifyDataChanged() will crash for dataset without entries #1945

Open
whvandervelde opened this issue Dec 11, 2016 · 7 comments
Open

notifyDataChanged() will crash for dataset without entries #1945

whvandervelde opened this issue Dec 11, 2016 · 7 comments
Labels

Comments

@whvandervelde
Copy link

More specifically
Setting CandleChartData with a dataset containing 0 entries and then calling data?.notifyDataChanged() will cause a crash.

I think this happens because it will try to reference entries using subscript index, so probably tries to get entries[0] (because count = 0) and that obviously won't work because that entries doesn't exist.

A workaround is to check if your dataset contains any entries and set it data to nil otherwise.

However, I think Charts could improve here by either using safe subscript referencing (so you can check entries[0] safely without crashing) or just checking if there are actual entries before trying to subscript access them.

@liuxuan30
Copy link
Member

liuxuan30 commented Dec 12, 2016

Well ah it used to check the count before rendering I remember, but I don't know its has been removed the check.
I checked that candle stick indeed crashes, however, bar chart doesn't, due to stride to/through difference.
Welcome file a PR to fix this :)

@whvandervelde
Copy link
Author

added PR #1948

There are checks for returned entry type throughout Charts, so returning nil seemed best here.

@liuxuan30
Copy link
Member

Thanks! Guess I need @danielgindi review it since I am not sure if I would miss anything. BTW, he's missing recently, so it might take a long time..

@cescobaz
Copy link

Same problem here, specially in real-time graph.
I get a lot of crashes for several reason during my development, but, at the end, I always found a workaround. This time I can't get the library working.

With the following example I will show up other bugs also.

func updateChart(value : double) {

    // not relevant code ...
    // ...    

    chartDataSet.addEntry(ChartDataEntry(x: Double(chartIndex), y: value ))
    
    // notify data change
    // if I comment the following line -> CRASH
    data.notifyDataChanged()

    // notify data change (again?)
    // if I comment the following line -> CRASH (again)
    chart.notifyDataSetChanged()

    // set the maximum visible range
    // why I do this fixed setup at every value update? Because if I set it at the moment of the chart creation it CRASHs
    chart.setVisibleXRangeMaximum(50)
    
    // calculate offset
    let offset = max (chartIndex - 50, 0 )

    // CRASH HERE (if I remove all datasets and re-add one or more -> crash)
    chart.moveViewToX(Double(offset))

    chartIndex += 1
}

I try to explain my scenario without more code because I can't copy all my code here, it is too long and not useful for your debug.
I load an empty graph and, when I start to get values from a stream I add values to the data set. To be precise I use more than one dataset. I have also several toggles that remove/add a dataset.

The crash happens when I switch off all the toggles, so no dataset in the chart.data exist, and I switch on one again (then adding again a dataset).

The errors I get are the following:

Error: CGAffineTransformInvert: singular matrix

fatal error: Double value cannot converted to Int because it is either infinite or NaN.

The above code works correcly until I remove all dataset and re-add at least one dataset. I tried to set chart.data = nill and then re-add data with/without dataset, it doesn't work.

I didn't read the source library code, but, in my opinion, the error is always the same, if you fix it, you will fix a lot of correlated bug.

Thanks!

@liuxuan30
Copy link
Member

liuxuan30 commented Jan 18, 2017

@cescobaz have you tried this PR, does it fix your crashes?

as much as I wanted to merge this, it will potentially impact many things, so I still need @danielgindi to review this not to missing anything :(

@cescobaz
Copy link

@liuxuan30 I just try this PR and it doesn't fix the bug.

The app logs many times the following error:

: Error this application or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix the problem.

Then, after a a few seconds of the above error appears multiple times in console, the app crash with:

fatal error: Double value cannot be converted to Int because it is either infinite or NaN

The last call I can see before crash is on line 125 of file ../Renderers/AxisRendererBase.swift

@cescobaz
Copy link

cescobaz commented Jan 18, 2017

Ok, I found a solution.

For some reason _xAxis._axisMinimum and _xAxis._axisMaximum are NaN when you set chart.data = nil or all the datasets are empty or there are no dataset in chart.data.
So I change my code to reset axisMinimum and axisMaximum every time. In the following the "new version" of the code above:

func updateChart(value : double) {

    // not relevant code ...
    // ...    

    chartDataSet.addEntry(ChartDataEntry(x: Double(chartIndex), y: value ))
    
    // calculate offset
    let xmax = 50
    let offset = max (chartIndex - xmax , 0 )

    // set max and min of xAxis because they are NaN when datasets are empty or chart.data == nil
    chart.xAxis.axisMinimum = Double(offset)
    chart.xAxis.axisMaximum = Double(offset + xmax)

    // notify data change
    data.notifyDataChanged()

    // notify data change
    chart.notifyDataSetChanged()

    // set the maximum visible range
    chart.setVisibleXRangeMaximum(Double(xmax))
    
    chart.moveViewToX(Double(offset))

    chartIndex += 1
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants