Taking a chart snapshot in iOS7

Written by Alison Clarke

We’re often asked how to take a snapshot of a ShinobiChart, and the answer used to be long and complex. In the past we’ve had to write a long blog post on the issue, and provided you with complex code snippets. But the good news is that since iOS7 taking a chart snapshot is incredibly easy!


There are two new methods on UIView in iOS7 which make snapshotting a breeze:

  • snapshotViewAfterScreenUpdates:renders a snapshot to a UIView.
  • drawViewHierarchyInRect:afterScreenUpdates: renders a snapshot into the current graphics context.

Snapshotting to a UIView

If you want to generate a snapshot to use within your app, then you should use the method snapshotViewAfterScreenUpdates:, which returns a UIView object representing the current state of the view.

All you need to do to create a snapshot of your chart is:

UIView *snapshotView = [_chart snapshotViewAfterScreenUpdates:NO];

The method takes a single parameter which determines whether to wait until any pending view updates have been applied. So if for example your chart might have just streamed some new data and you want to make sure it’s included, then use:

UIView *_snapshotView = [_chart snapshotViewAfterScreenUpdates:YES];

You could make use of this method to create a simpler view for better performance if you wanted to use some animation effect on the chart, e.g. to transition between screens.

Snapshotting to a UIImage

If you want you want to save a screenshot of your chart to a UIImage, so your users can share it or save it to their device, then the method drawViewHierarchyInRect:afterScreenUpdates:is your friend. Here’s what you need to do:

// Create an image context - the size of chart and the scale of the device screen
UIGraphicsBeginImageContextWithOptions(_chart.bounds.size, NO, 0.0);
// Render our snapshot into the image context
[_chart drawViewHierarchyInRect:_chart.bounds afterScreenUpdates:NO];

// Grab the image from the context
UIImage *chartImage = UIGraphicsGetImageFromCurrentImageContext();
// Finish using the context

The first line creates a bitmap graphics context. The next calls the new view drawing method, to snapshot the chart into the new context. (Again, the second parameter determines whether to wait for pending updates before taking the snapshot.) Next, we create a UIImage from the context, and finally we clean up the image context. The UIImage is then ready to be shared or saved.

Note that this method is slower than snapshotViewAfterScreenUpdates:, so if you can use a UIView rather than a UIImage it’s probably better to use snapshotViewAfterScreenUpdates.

Supporting older versions

If your app still needs to run on iOS6, then I’m afraid you’ll still have to do things the hard way. Happily we’ve already done most of the work for you: download ShinobiChart+Screenshot.h and SChartGLView+Screenshot.h from our GitHub project, then you can use the new methods provided by these categories.

To snapshot to a UIImage, call the snapshot method on your chart:

UIImage *imageOfYourChart = [_chart snapshot];

If you’ve got any views which are drawn above the data on your chart, such as pie chart labels or annotations, then you’ll have to use the addViewToSnapshot:addToGLView: method provided by the category.

For example, to add pie chart labels to your snapshot image, you could implement the following SChartDelegate method:

-(void)sChart:(ShinobiChart *)chart alterLabel:(UILabel *)label forDatapoint:(SChartRadialDataPoint *)datapoint atSliceIndex:(int)index inRadialSeries:(SChartRadialSeries *)series {
    [_chart addViewToSnapshot:label addToGLView:YES];

Hopefully this post will have shown you how to create a chart snapshot in iOS7. Any questions? Give us a shout.