After developing LinkLite for iPhone, I decided to share with you my experience in this area by publishing the Objective-c class used to draw a pie chart. This time I would not give you that code snippets to make a pie chart, this being due to the specificity of the goal.
Preliminary :
To make a pie must first have data to display, and perform an array dedicated to the creation of the pie.
First look at the type of data contained in your array, it could be for example:
//
// Class_Item.h
//
@interface Your_Array_Item : NSObject {
NSString* time;
NSString* ip;
NSString* system;
NSString* browser;
NSString* version;
NSString* resolution;
NSString* language;
NSString* referer;
NSString* isp;
}
@property (nonatomic, retain) NSString* time;
@property (nonatomic, retain) NSString* ip;
@property (nonatomic, retain) NSString* system;
@property (nonatomic, retain) NSString* browser;
@property (nonatomic, retain) NSString* version;
@property (nonatomic, retain) NSString* resolution;
@property (nonatomic, retain) NSString* language;
@property (nonatomic, retain) NSString* referer;
@property (nonatomic, retain) NSString* isp;
@end
//
// Class_Item.m
//
#import "Class_Item.h"
@implementation Your_Array_Item
@synthesize time;
@synthesize ip;
@synthesize system;
@synthesize browser;
@synthesize version;
@synthesize resolution;
@synthesize language;
@synthesize referer;
@synthesize isp;
@end
Then look at the type of data contained in our array for display:
//
// Class_Array_Item.h
//
@interface Array_Item_To_Show: NSObject {
NSString* Info; // Title of the pie part
UIColor* Color; // Color of the pie part
double Percent; // percent of the pie part ( 0.33 => 33% )
double CountItem; // the number of similare item found, this number is for percent calculation
}
@property (nonatomic, retain) NSString* Info;
@property (nonatomic, retain) UIColor* Color;
@property double Percent;
@property double CountItem;
@end
//
// Class_Array_Item.m
//
#import "Class_Array_Item.h"
@implementation Array_Item_To_Show
@synthesize Info;
@synthesize Color;
@synthesize Percent;
@synthesize CountItem;
@end
In your view controller (or other) you must define this
@interface YourViewController : UIViewController {
...
NSMutableArray* YourDataArray; // Your data array
NSMutableArray* PieItemArray; // Array of Array_Item_To_Show
...
}
and initialize to avoid exeption !
- (void) viewDidLoad {
...
YourDataArray = [[NSMutableArray arrayWithCapacity:0] retain];
PieItemArray = [[NSMutableArray arrayWithCapacity:0] retain];
...
}
To convert YourDataArray to PieItemArray you can write this fuction
//------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------
- (UIColor*) GetRandomColor
{
CGFloat red = (CGFloat)random()/(CGFloat)RAND_MAX;
CGFloat blue = (CGFloat)random()/(CGFloat)RAND_MAX;
CGFloat green = (CGFloat)random()/(CGFloat)RAND_MAX;
return [UIColor colorWithRed: red green: green blue: blue alpha: 1.0];
}
//------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------
- (BOOL) CheckIfExistInArray : (NSArray*) Array : (NSString*) Search
{
for (int i=0; i < Array.count; i++){
Array_Item_To_Show* Item = [Array objectAtIndex:i];
if ( [Item.Info isEqualToString: Search] ){
[[Array objectAtIndex:i] setCountItem: [[Array objectAtIndex:i] CountItem] + 1];
return YES;
}
}
return NO;
}
//------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------
- (void) GetFinalArray : (NSString*) ItemFieldName
{
int i;
//--------------------------------------------------------------------------
// declaration of new temp array for result
NSMutableArray* TmpArray = [[NSMutableArray arrayWithCapacity:0] retain];
//--------------------------------------------------------------------------
// declaration of your array count item
int ArrayCountValue = DataArray.count;
//--------------------------------------------------------------------------
// declaration of Temp item to add in TmpArray
Array_Item_To_Show* NewItem;
//--------------------------------------------------------------------------
// declaration of your array item type
Your_Array_Item* YourArrayItem;
//--------------------------------------------------------------------------
// declaration of Percent number
NSNumber* Percent;
//--------------------------------------------------------------------------
// get all symilarity item and count
//--------------------------------------------------------------------------
for (i = 0; i < ArrayCountValue; i++){
YourArrayItem = [YourDataArray objectAtIndex:i];
if ( [self CheckIfExistInArray: TmpArray : [YourArrayItem valueForKey: ItemFieldName] ] == NO ){
//--------------------------------------------------------------------------
// add item if not exists !
NewItem = [Array_Item_To_Show alloc];
[NewItem setInfo: [YourArrayItem valueForKey:ItemFieldName] ];
[NewItem setCountItem: 1];
[TmpArray addObject: NewItem];
}
}
//--------------------------------------------------------------------------
// Compute percent for each items
//--------------------------------------------------------------------------
for (i=0; i < TmpArray.count; i++){
NewItem = [TmpArray objectAtIndex:i];
Percent = [NSNumber numberWithFloat:( 360 * (NewItem.CountItem / ArrayCountValue) )];
//--------------------------------------------------------------------------
// Assign a percent to pie part
[NewItem setPercent: [Percent floatValue]];
//--------------------------------------------------------------------------
// Assign a color to pie part
[NewItem setColor: [self GetRandomColor]];
}
//--------------------------------------------------------------------------
// empty the final array that contain result
[PieItemArray removeAllObjects];
//--------------------------------------------------------------------------
// Sort result array by percent
NSSortDescriptor* Descriptor = [[[NSSortDescriptor alloc] initWithKey:@"Percent" ascending: NO] autorelease];
//--------------------------------------------------------------------------
// finally fill the final array with the sorted temp array
[PieItemArray addObjectsFromArray: [TmpArray sortedArrayUsingDescriptors:[NSArray arrayWithObject: Descriptor]]];
}
The function to draw a pie chart with PieItemArray is show bellow :
//------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------
- (UIImage*) DrawPieWithArray : (CGFloat) PieRadius : (CGFloat) TopLeftBorder
{
CGFloat CenterX = PieRadius + TopLeftBorder;
CGFloat CenterY = PieRadius + TopLeftBorder;
CGFloat StartRad = 0;
CGFloat EndRad = 0;
//---------------------------------------------------------------------------------------
CGColorSpaceRef _ColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef _ViewContext = CGBitmapContextCreate (NULL, 2*CenterX, 2*CenterY, 8, 0, _ColorSpace, kCGImageAlphaPremultipliedLast);
if (_ViewContext == NULL){
CGColorSpaceRelease(_ColorSpace);
return nil;
}
//---------------------------------------------------------------------------------------
CGContextSetRGBStrokeColor(_ViewContext, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(_ViewContext, 4.0);
//---------------------------------------------------------------------------------------
for (NSUInteger i = 0; i< PieItemArray.count; i++){
Array_Item_To_Show* Item = [PieItemArray objectAtIndex:i];
//-------------------------------------------------------------
// set the pie part color
const CGFloat* RGBComponents = CGColorGetComponents( [Item.Color CGColor] );
CGContextSetRGBFillColor(_ViewContext, RGBComponents[0], RGBComponents[1], RGBComponents[2], 1.0 );
//-------------------------------------------------------------
// Compute the finale angle for the pie part arc
EndRad = StartRad + Item.Percent;
//-------------------------------------------------------------
// draw the pie part
CGContextMoveToPoint(_ViewContext, CenterX, CenterY);
CGContextAddArc(_ViewContext, CenterX, CenterY, PieRadius, radians(StartRad), radians(EndRad), 0);
CGContextClosePath(_ViewContext);
CGContextFillPath(_ViewContext);
StartRad = EndRad;
}
//--------------------------------------------------------------------------------------
// Option : to improve rendering, you can add an overlay image on the top of the pie
// See bellow for image example.
CGImageRef OverlayImage = [[UIImage imageNamed: @"cam_overlay.png" ] CGImage];
CGContextDrawImage(_ViewContext, CGRectMake( 0.0, 0.0, CGImageGetWidth(OverlayImage), CGImageGetHeight(OverlayImage) ), OverlayImage);
//---------------------------------------------------------------------------------------
// Create UIImage with context
CGImageRef _BitmapContext = CGBitmapContextCreateImage(_ViewContext);
UIImage* Result = [UIImage imageWithCGImage: _BitmapContext];
//---------------------------------------------------------------------------------------
// free all resource !
CGContextRelease(_ViewContext);
CGColorSpaceRelease(_ColorSpace);
CGImageRelease(_BitmapContext);
return Result;
}
Bellow an example of overlay image used with LinkLite :

Finally to get a visual result you must :
1 – Fill your DataArray
2 – Call « GetFinalArray » function like this to show a pie chart with browser item for example !
[self GetFinalArray : @"browser"];
3 – Call « DrawPieWithArray » function and fill your image with the result
[your_Pie_img setImage: [self DrawPieWithArray : 60.0 : 6.0]];
Now you are ready to show pie chart on your iPhone / iPad / iPod !


Thanks for the info