I was looking for a graphing solution for iOS when I ran across a great project called Core Plot. According to the overview it is described as a 2D plotting framework for Mac OS X and iOS. It is highly customizable and capable of drawing many types of plots.
The project is well organized and includes some nice iOS API documentation. I started by looking for a tutorial and found a comprehensive one on Ray Wenderlich’s site. Steve Baranski wrote a detailed article in 2 parts on using Core Plot titled “How To Draw Graphs with Core Plot” – Part 1 and Part 2.
I decided to create an iPad demo project which I call “Algorithms” and release it to GitHub.
My first use of Core Plot was to simulate the rolling of 2 dice, graphing the number of times that the roll counts 2-12 come up.
Horizontal Label positioning
For the X axis, I needed labels with the text “2” through “12”.
My first attempt at creating these labels used code such as in the following snippet:
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init]; axisTextStyle.color = [CPTColor whiteColor]; axisTextStyle.fontName = @"Helvetica-Bold"; axisTextStyle.fontSize = 11.0f; // Label labelStr ranges from "2" - "12" CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:labelStr textStyle:axisTextStyle]; CGFloat location = locIndex++; label.tickLocation = CPTDecimalFromCGFloat(location); label.offset = 4.0; // Vertical spacing of label from X axis label.alignment = CPTTextAlignmentLeft;
Note that I can control the alignment of the label text with the above code, but not the precise horizontal spacing.
After some searches, I found that others were having the same issue with trying to control the horizontal spacing.
The simplest solution I found was to use the CPTAxisLabel method initWithContentLayer:
CGFloat hostViewWidth = self.hostView.bounds.size.width; CGFloat graphWidth = hostViewWidth - self.hostView.hostedGraph.paddingLeft - self.hostView.hostedGraph.paddingRight; CGFloat recordWidth = graphWidth/11.0; // Width of a plot record. We have 11 distinct plot records CGFloat barCenterLeftOffset = recordWidth * BarInitialX; // Center of plot record CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:labelStr style:axisTextStyle]; CGSize textSize = [textLayer sizeThatFits]; // Calculate the padding needed to center the label under the plot record. textLayer.paddingLeft = barCenterLeftOffset - textSize.width/2.0; CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithContentLayer:textLayer];
This worked perfectly to give me the control that I was looking for. For the full context of this code, please see the file TwoDiceRollSimulationView.m and the method configureAxes in my GitHub algorithms project.
In developing the Algorithms iPad app as a display of the power of Core Plot, I ended up with a nice demonstration of some other topics that were of interest to me.
Over time I may add some other more interesting algorithms to the project and I wanted a way to easily share this code with a user of the app.
If a user is interested in getting a copy of some code, I provide the ability for them to e-mail it to themselves as attachments. Allowing the app to read the code directly was not straightforward. I use links that I add to Bundle Resources as documented in the README file of the project.