0

I have created a scatter plot using Core Plot. My graph however needs to be refreshed dynamically (points are constantly being added and removed). I need the plot to be fluent and appear to be "sliding across the graph". Instead I seem to be getting a choppy line that adds several values at once, freezes and the again adds several values. What could be causing this behaviour?

-(void)updateDataWithVal:(double)percentageUsage
{
    if ([self.graphData count] >= 10)
    {
        [self.graphData removeLastObject];
    }
    [self.graphData insertObject:[NSNumber numberWithDouble:percentageUsage]  atIndex: 0];
    [self.graph reloadData];
}

Above is the function that is called every time I want the graph to change. The problem isn't with the data being updated. I debugged the function and noticed that the data is being updated fluently (a point is added and removed from the data array per second). The problem is with the graph actually changing. What could be causing the graph to freeze and adding several points at once (every 6-7 seconds) instead of continuously updating every second like the data is?

I doubt this is being caused by adding to many points in a short interval. Only one point is removed and added per second. Additionally, my graph has only one plot.

My graph is running on OSX not iOS. All code is in Objective-C.

fdh
  • 5,256
  • 13
  • 58
  • 101
  • Is the data point adding being done in a tight loop, or is the main thread being tied up in some other way? It sounds like the main run loop isn't being allowed to run its course and update the UI on every data point insertion, but it gets freed up every now and then. – Brad Larson Aug 20 '12 at 20:50
  • @BradLarson Thanks for answering! 1) What exactly is a tight loop? 2) I doubt if this is caused by the main thread not being able to run its course - the above function is run on a separate thread, therefore it wouldn't interfere with the main thread. – fdh Aug 20 '12 at 21:05
  • By tight loop, I mean a for loop or some other iteration that rarely or never exits, never allowing the main run loop to go to completion. However, now that you mention it you should be aware that any manipulation of this graph needs to occur on the main thread, because we're dealing with display elements here. Otherwise, you can get irregular behavior or even crashes. – Brad Larson Aug 20 '12 at 21:07
  • @BradLarson Nope, no tight loop. I need my graph to be continually updated though - if I run this on the main thread, wouldn't this freeze my main thread? How can I possibly run a continuously updating graph on the main thread? – fdh Aug 20 '12 at 21:15
  • Grab the data on a background thread / queue, then dispatch just the method above asynchronously on the main thread / queue. I use this for real-time data display of a sensor I have which updates once every 30 ms. – Brad Larson Aug 20 '12 at 21:19
  • @BradLarson I have absolutely no idea how to dispatch the method asynchronously on the main thread. By any chance could you please provide a code example or refer me to one? – fdh Aug 20 '12 at 21:23
  • Both synchronous and asynchronous variants using GCD are shown in this question (async in the question, a safe synchronous variant in my answer): http://stackoverflow.com/questions/5662360/gcd-to-perform-task-in-main-thread , but before you get too far into that I highly recommend watching the WWDC 2010 sessions on GCD and reading the Concurrency Programming Guide: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html – Brad Larson Aug 20 '12 at 21:26
  • 1
    @BradLarson Thank You! That worked like a charm. Could you please post your comment as an answer so I can select it as the best answer? – fdh Aug 20 '12 at 21:57

1 Answers1

1

As requested, I can convert my comments into an answer so that this can closed out.

Core Plot graphs are heavily reliant on display elements, so any updates to them must be performed on the main thread. Otherwise, you will see odd rendering behavior like inconsistent updates, visual artifacts, and your application most likely will crash at some point.

I have to do the same thing that you describe within one of my Mac applications. For this, I use a background GCD queue to handle the data acquisition and processing to avoid blocking the main thread. However, every time that I need to insert the results into the graph and have it update, I use dispatch_async() to wrap the appropriate code in a block to be performed on the main thread. This should protect you against rendering oddities like what you see here.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571