Pie Chart Drawing in iPhone Using Core Plot Library

Introduction to Core Plot

Core Plot is an open source and free charting library for building iPhone and Mac applications. In this article I will show you how you can create a Pie Chart in an iPhone application using Core Plot. Once you learn the basics of Core Plot, it is quite easy to generate a wide range of graphs including line charts and bar charts. Click here to visit the homepage of Core Plot library.

Downloading and Installing Core Plot

Core Plot library is still under constant development and there is no direct package available for download. You need to download the Core Plot source code directly from the Mercurial version control repository. Hence you will require Mercurial client for Mac for downloading Core Plot. First download and install Mercurial client from this link.

After installing Mercurial client, create a folder in your system where you want the Core Plot library downloaded. Then using the terminal application, change to this folder. Type the following command on the terminal  to get the Core Plot library,

hg clone http://core-plot.googlecode.com/hg/ core-plot

It may take a while to download Core Plot library source code.

Setting up a Sample iPhone Project in Xcode

Let us now create a sample iPhone project in Xcode. We will use this sample project to create Pie Charts using Core Plot.

Open Xcode and select new project and then select view based application. Name the project as "PieChart Sample". This will create a sample iPhone project with a default ViewController. We will be using the view of this ViewController to draw Pie Charts. Click on "build and run" to run the view based application. Note that in Core Plot you can draw charts to any view. For example, you can draw charts even in table rows.

The sample project will generate the following files,

  • PieChart_SampleAppDelegate.h and PieChart_SampleAppDelegate.m – The sets up the view for the application. We won’t change this.
  • PieChart_SampleViewController.h and PieChart_SampleViewController.m – This is the controller object for handling the default view. We will modify this view controller to draw a Pie Chart on the view.

Piechart sample code in Xcode - Step 1 You will also find other files such as the MainWindow.xib and PieChart_Sample-info.plist in the sample project. For the Pie Chart sample, we won’t be changing any of these. So let us ignore these.

The screenshot on the right shows the structure of the sample project at this stage.

In Core Plot, the framework is modeled as a static library. This is because iPhone terms doesn’t allow linking to a dynamic library. Hence before you can use Core Plot in your project, you need to configure some settings in Xcode for linking a static library.

Adding Coreplot to an iPhone project First we will add the Core Plot Xcode project as a child to the PieChart Sample. For this drag the project file CorePlot-CocoaTouch.xcodeproj from the core-plot/framework folder (this is located under folder where you have downloaded Core Plot) to the PieChart Sample project in Xcode. Ensure that you uncheck the "copy items to destination
group’s folder" option (see screenshot on the left).

Once you add the Core Plot project, it is available as a binary in your iPhone project as shown in the screenshot below.

Core plot as a dependent project in an iPhone project

Link Binary with Libraries (static link to core plot) Now drag the file libCorePlot-CocoaTouch.a under the Core Plot project to "Link Binaries with Libraries" node in your application’s target. It will now appear under the Targets folder (see screenshot to the right).

Right click on your sample application target and then click on Get Info. In General ->  Direct Dependencies add CorePlot-CocoaTouch. This ensures that the Core Plot library is built whenever we build our sample application. The General tab will look like the screenshot below.

Adding direct dependencies to Core Plot (for auto build) 

Since we are including the Core Plot as a statically linked library, Xcode needs to know the location of the headers required by our sample application. We will be importing the Core Plot file "CorePlot-CocoaTouch.h" in our source code. CorePlot-CocoaTouch.h internally imports all headers required in a Core Plot application.

To add header location, right click the sample project and click on Get Info. Select the Build tab. Click on the field "search in Build settings" and type in "Header Search Paths". This will filter the build settings table below to show only the "Header Search Paths" setting. Double click on "Header Search Paths" row and then enter the full path to the core-plot/framework folder. Also ensure that you check the "recursive" flag. Refer to the screenshot below.

Adding header search paths for a Core Plot project 

In addition to the header paths, you also need to set a couple of linker flags. Again, right click the sample project and then select Get Info. From the build tab, click the field "search in Build settings" and type in "Other Linker Flags". Double click on "Other Linker Flags" row and then enter the flags -ObjC and -all_load as shown below.

Configuring linker flags for a Core Plot project

Lastly since Core Plot uses Quartz framework for graphics, you need to add it to the "Linked Libraries" section. Right click on PieChart Sample under the Targets group and click on Get Info. Under "Linked Libraries" add QuartzCore.framework.

Adding Quartz framework to an iPhone project in Xcode

Now "Build and Run" to check that everything is in order. If you are getting any errors, double check all the steps mentioned above.

Enough of Xcode configuration, let us write some real code!

Drawing Pie Chart using Core Plot

We will be drawing the Pie Chart in  PieChart_SampleViewController. So first import the file "CorePlot-CocoaTouch.h" in PieChart_SampleViewController.m file,

	#import "CorePlot-CocoaTouch.h"

One of the requirements of Core Plot is that it can only draw to an instance of CPLayerHostingView. The good thing is that you can replace any view with CPLayerHostingView. So let us change the view member of the PieChart_SampleViewController with an instance of CPLayerHostingView. The loadView method can be overridden to setup the view manually.

 
- (void)loadView {
	CPLayerHostingView * newView = [[CPLayerHostingView alloc]initWithFrame:[[UIScreen mainScreen] applicationFrame]];
	self.view = newView;
	[newView release];
}

Core Plot in action! Now is a good time go through the Core Plot high level design to get an idea of the Core Plot architecture. Currently there is very limited documentation when it comes to Core Plot API. The best reference obviously is the source code itself.

In our sample application, we will use CPXYGraph as the graph container for our Pie Chart. Then we will use the CPPieChart to draw a Pie Chart inside the CPXYGraph. finally CPXYGraph itself will be added to the CPLayerHostingView. We will do the Pie Chart drawing in the viewDidLoad method of PieChart_SampleViewController.

First we will add an instance of CPXYGraph as a member of the view controller (PieChart_SampleViewController) and then we will add a NSMutableArray to store the data required by the Pie Chart. We will also define the view controller as a Pie Chart data source by conforming to the CPPieChartDataSource protocol.

This is the revised and complete PieChart_SampleViewController.h file,

#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
 
 
@interface PieChart_SampleViewController : UIViewController <CPPieChartDataSource>{
 
	CPXYGraph * graph;
	NSMutableArray *pieData;
}
@property(readwrite, retain, nonatomic) NSMutableArray *pieData;
@property (nonatomic,retain) CPXYGraph * graph;
 
@end

We will synthesize the graph and pieData properties in PieChart_SampleViewController.m,

@synthesize graph,pieData;

Let us now implement the viewDidLoad method in PieChart_SampleViewController.m,

First we will setup the graph,

graph = [[CPXYGraph alloc] initWithFrame: self.view.bounds];	
CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
hostingView.hostedLayer = graph;

Then we will setup the Pie Chart,

CPPieChart *pieChart = [[CPPieChart alloc] init];
pieChart.dataSource = self;
pieChart.pieRadius = 100.0;
pieChart.identifier = @"PieChart1";
pieChart.startAngle = M_PI_4;
pieChart.sliceDirection = CPPieDirectionCounterClockwise;

dataSource indicates the object which conforms to the CPPieChartDataSource protocol. We will set PieChart_SampleViewController itself as the data source. pieRadius indicates the radius in pixels.

Now let us load the data for the Pie Chart in a member variable (in a real application this chart data will come from a database or a web service),

self.pieData=  [NSMutableArray arrayWithObjects:[NSNumber numberWithDouble:90.0], 
			[NSNumber numberWithDouble:20.0],
			[NSNumber numberWithDouble:30.0],
			[NSNumber numberWithDouble:40.0],
			[NSNumber numberWithDouble:50.0], [NSNumber numberWithDouble:60.0], nil];

Finally add the Pie Chart to the graph and release the Pie Chart,

[graph addPlot:pieChart];
[pieChart release];

Now we need to setup two methods required by the CPPieChartDataSource protocol. Note that we had setup the data source as PieChart_SampleViewController by calling     pieChart.dataSource = self; This means that whenever Core Plot requires data for drawing Pie Chart it will call methods numberOfRecordsForPlot and numberForPlot:field:recordIndex:. Let us implement these,

-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot
{
    return [self.pieData count];
}
 
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index 
{
	return [self.pieData objectAtIndex:index];
}

The first method returns the total number of pies in the chart. The second one returns the value for a pie slice indicated by the recordIndex.

We also need to ensure that all objects are released during dealloc. Here is the complete listing of PieChart_SampleViewController.m,

#import "PieChart_SampleViewController.h";
 
@implementation PieChart_SampleViewController
 
@synthesize graph,pieData;
 
- (void)loadView {
 
	CPLayerHostingView * newView = [[CPLayerHostingView alloc]initWithFrame:[[UIScreen mainScreen] applicationFrame]];
	self.view = newView;
	[newView release];
}
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
	graph = [[CPXYGraph alloc] initWithFrame: self.view.bounds];	
	CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
	hostingView.hostedLayer = graph;
 
	CPPieChart *pieChart = [[CPPieChart alloc] init];
	pieChart.dataSource = self;
	pieChart.pieRadius = 100.0;
	pieChart.identifier = @"PieChart1";
	pieChart.startAngle = M_PI_4;
	pieChart.sliceDirection = CPPieDirectionCounterClockwise;
 
	self.pieData=  [NSMutableArray arrayWithObjects:[NSNumber numberWithDouble:90.0], 
							[NSNumber numberWithDouble:20.0],
							[NSNumber numberWithDouble:30.0],
							[NSNumber numberWithDouble:40.0],
							[NSNumber numberWithDouble:50.0], [NSNumber numberWithDouble:60.0], nil];
 
 
	[graph addPlot:pieChart];
	[pieChart release];	
 
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot
{
    return [self.pieData count];
}
 
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index 
{
	return [self.pieData objectAtIndex:index];
}
 
 
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
 
- (void)viewDidUnload {
}
 
 
- (void)dealloc {
	[pieData release];
	[graph release];
	[super dealloc];
}
 
@end

Changing the Appearance of Core Plot Pie Chart

Changing Background of Pie Chart – You can easily change the background of a Pie Chart by using themes. For example, applying the following theme will display a different background,

CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];

 image

The themes available in Core Plot are kCPDarkGradientTheme, kCPPlainWhiteTheme, kCPPlainBlackTheme, kCPSlateTheme and kCPStocksTheme. To get the latest list of themes supported, please refer to the source code.

Changing the fill style of a Pie Slice  – If you really want to customize how the slices are generated for a Pie Chart, you can override the method -(CPFill *)sliceFillForPieChart:(CPPieChart *)pieChart recordIndex:(NSUInteger)index;  in your Pie Chart data source. This method allows you to customize fill colors for each of the slices or even better you can use gradient fills for slices!

The following implementation uses rainbow colors for all the slices in the chart. It is also possible to construct a custom gradient object.

-(CPFill *)sliceFillForPieChart:(CPPieChart *)pieChart recordIndex:(NSUInteger)index {
	CPFill * fill = [CPFill fillWithGradient:[CPGradient rainbowGradient]];
	return fill;
}

Download Pie Chart Sample Code

Click here to download the code for the Core Plot Pie Chart Sample project.

Click here to get latest site updates delivered to your email. You need to confirm subscription by clicking on the link sent by feedburner to your email address.


April 9, 2011 | Posted in Programming 6 Comments » | By Jayson Joseph

6 Comments to “Pie Chart Drawing in iPhone Using Core Plot Library”

  1. Didier Says:

    Your example is using CPLayerHostingView but it’s a Mac only class.
    For iphone we need to replace it with CPGraphHostingView.

    I think it will help a lot of people. I took me more than an hour to figure it out.

  2. Tiago Sousa Says:

    Excelent! Exactly what i was looking for

    I just wanted to know if this supports animations automaticly,
    or we have to make those…

  3. ning883 Says:

    Hi,

    i keep on getting

    /Users/junxu94/Documents/PieChart Sample/Classes/PieChart_SampleViewController.h:14:0 /Users/junxu94/Documents/PieChart Sample/Classes/PieChart_SampleViewController.h:14: error: cannot find protocol declaration for ‘CPPieChartDataSource’

    Any suggestions pls ? i’m new on Mac. Thanks !

  4. Prof Von Lemongargle Says:

    ning883 – All of the class names were changed after the article was written. The CP prefix has been changed to CPT. So, CPPieChartDataSource is now CPTPieChartDataSource. HTH – Prof

  5. cdresche Says:

    This step…

    “Right click on your sample application target and then click on Get Info. In General -> Direct Dependencies add CorePlot-CocoaTouch. This ensures that the Core Plot library is built whenever we build our sample application. The General tab will look like the screenshot below.”

    keeps crashing my Xcode 4. Is there a compatibility problem due to Xcode versioning?

  6. Shekhar Sharma Says:

    Very Nice Doc..Really helpful.

    In Xcode4 Go on build phase->Target Dependanicies .Then add there CorePlot-CocoaTouch.

Leave a Comment