The need to display a graph of some kind comes up surprisingly often when developing applications. Because of this, for almost every language and framework under the sun, there is some sort of graphing/plotting library (and sometimes a lot more than just one). While there is no built in library for graphing for iPhone applications, there is an open source library called Core Plot. This library is under active development and can be used to create a number of different types of graphs - if you want, you can check our their example page here.
Today we are going to be taking a look at how to get this library into your iPhone application, as well as how to use it to create a simple plot. But before we can do anything, first you have to go get the source for Core Plot. Because the library is still relatively new and under quick active development, there are no packages available - you have to get the source code straight from Core Plot's repository. So as a first step, you probably need to install Mercurial. Once you have that, getting the source is a simple matter of the following command:
That last argument (in our case here core-plot) is the directory you want to check the code out to. Ok, now that we have the code, what do we do? Well, let's get an iPhone Xcode project going! For this tutorial, our project is going to be named "SOTC-CorePlotTest". The first thing to do after you get an Xcode project off the ground is drag the CorePlot-CocoaTouch.xcodeproj file from the core-plot/framework directory into your new project. When you do that, you will get the following dialog:
The defaults are fine - most of the time we don't want to copy the entire library into your project - we just want a reference to wherever you checked our core-plot. So leave "Copy items into destination group's folder" unchecked. One you click "Add" on this dialog, an entry for CorePlot-CocoaTouch.xcodeproj will show up the "Groups & Files" tree for your project:
Because the iPhone core-plot is a static library, it needs to be linked with your application. To do this, you need to grab the entry libCorePlot-CocoaTouch.a from the "Groups & Files" (it is a child of the CorePlot-CocoaTouch.xcodeproj entry) and drag it to "Link Binaries with Libraries" node in your application's target:
Now we have to tell Xcode that our application is dependent on the core plot library - that way the library gets built when we build our app. This is done in the settings window for the application target. Under the "General" tab, you can add CorePlot-CocoaTouch as a direct dependency:
But don't think we are done yet! Now we have to modify some build settings. You do this by going to the "Build" tab of the project settings (not the build tab of the settings widow you were just in - those were build settings for the target). In here there are two properties that we have to modify: "Header Search Paths" and "Other Linker Flags". There are a lot of properties, but fortunately Apple gives us a little filter box to find the properties that we want. So first, "Header Search Paths". Here we need to add the full path to the core-plot/framework directory:
Then we need to add the -ObjC linker flag, which causes the linker to "Loads all members of static archive libraries that define an Objective C class or a category". We need this flag because Core Plot uses Objective C categories on existing classes, and when compiling against it as a static library, the code for the categories is not linked into the final executable. This flag forces that code to be included.
Ok, we are almost done with all this configuration - just one more step. We have to add the built in Core Animation library to our project, because Core Plot is built on top of Core Animation. To do this, you add the QuartzCore framework to the project. Right click on the Frameworks folder in the "Groups & Files" tree and choose Add->Existing Framework and browse for QuartzCore:
Whew! We are finally set to actually start using Core Plot. If you created a simple window project when you started, you probably have an AppDelegate and a ViewController class in your classes folder (mine here are "CorePlotTestAppDelegate" and "CorePlotTestViewController"). We aren't going to worry about the AppDelegate class today - all the code we are going to write will be in the ViewController. So start off by pulling up the .h file for your controller (in my case "CorePlotTestViewController.h"). It probably looks something like this at the moment:
@interface CorePlotTestViewController : UIViewController
{
}
@end
Not much will change in this file, but there are a few things we are going to need to add:
#import "CorePlot-CocoaTouch.h"
@interface CorePlotTestViewController : UIViewController <CPPlotDataSource>
{
CPXYGraph *graph;
}
@end
First off, we need to reference the Core Plot libraries with an import statement. Since this is an iPhone application, we pull in the "CocoaTouch" version of the header file. Now that we have that, we can make the other two changes - an instance variable (to hold our graph) and a protocol. The variable is self explanatory, but the protocol probably needs some explanation. In this case, this view controller is going to be the data source for our graph, and so it has to implement the protocol CPPlotDataSource. This protocol is defined in Core Plot and consists of two functions:
-(NSUInteger)numberOfRecords;
@optional
// Implement one of the following
-(NSArray *)numbersForPlot:(CPPlot *)plot
field:(NSUInteger)fieldEnum
recordIndexRange:(NSRange)indexRange;
-(NSNumber *)numberForPlot:(CPPlot *)plot
field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index;
-(NSRange)recordIndexRangeForPlot:(CPPlot *)plot
plotRange:(CPPlotRange *)plotRect;
@end
Well, four functions actually, but you only have to implement two of them. The first one is a getter for the number of data points on the plot (numberOfRecords), and the last three (of which you need to implement one) are functions for getting the specific value for a particular data point.
Ok, that is it for talking about our ViewController header file - but before we move on to the actual implementation, we have to do one other thing. A core plot graph cannot be hosted in just any UIView - it has to be hosted in a CPLayerHostingView. To get this to happen we have to change the base type of our view. So pull open the xib file for the view for this view controller, and change the base type of the view to CPLayerHostingView in the Identity Inspector:
Finally, some implementation code! We will start off with the implementation of the protocol you saw above. In our case we will actually be drawing two plots on one graph - one being the function x^2, and the other being 1/x:
return 51;
}
-(NSNumber *)numberForPlot:(CPPlot *)plot
field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index
{
double val = (index/5.0)-5;
if(fieldEnum == CPScatterPlotFieldX)
{ return [NSNumber numberWithDouble:val]; }
else
{
if(plot.identifier == @"X Squared Plot")
{ return [NSNumber numberWithDouble:val*val]; }
else
{ return [NSNumber numberWithDouble:1/val]; }
}
}
For these plots, I am explicitly returning 51 data points spread over the x range -5 to 5. In a real application the data would probably be coming from somewhere, like a file or user input, but here we are just graphing functions. When numberForPlot is called, I take the data point index passed in and transform it to an x value between -5 and 5. If the function was called asking for the X value (when fieldEnum is CPScatterPlotFieldX), I just return it. Otherwise, depending on the the identifier of the plot, I return the value either squared or inverted.
So that takes care of generating data for the graph. Now we need to take care of the creation of the graph itself:
[super viewDidLoad];
graph = [[CPXYGraph alloc] initWithFrame: self.view.bounds];
CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
hostingView.hostedLayer = graph;
graph.paddingLeft = 20.0;
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 20.0;
If you remember from the header file, graph is a instance variable, and here we are finally populating it. Here we are creating a CPXYGraph (currently the only type of graph Core Plot offers), and then setting it as the hosted layer in our view (which is actually a CPLayerHostingView thanks to the change in the xib file earlier). We also set some padding here to give the graph some space on the screen.
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-6)
length:CPDecimalFromFloat(12)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-5)
length:CPDecimalFromFloat(30)];
A Core Plot graph can have many PlotSpaces. A PlotSpace is where individual plots live - but all plots in a plot space share the same range. In this case, we only need one PlotSpace, so we grab the default one. Here we are setting the x and y range of the plot space - one thing to note is that range is set in terms of position and length, not minimum and maximum values.
lineStyle.lineColor = [CPColor blackColor];
lineStyle.lineWidth = 2.0f;
axisSet.xAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.xAxis.minorTicksPerInterval = 4;
axisSet.xAxis.majorTickLineStyle = lineStyle;
axisSet.xAxis.minorTickLineStyle = lineStyle;
axisSet.xAxis.axisLineStyle = lineStyle;
axisSet.xAxis.minorTickLength = 5.0f;
axisSet.xAxis.majorTickLength = 7.0f;
axisSet.xAxis.axisLabelOffset = 3.0f;
axisSet.yAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.yAxis.minorTicksPerInterval = 4;
axisSet.yAxis.majorTickLineStyle = lineStyle;
axisSet.yAxis.minorTickLineStyle = lineStyle;
axisSet.yAxis.axisLineStyle = lineStyle;
axisSet.yAxis.minorTickLength = 5.0f;
axisSet.yAxis.majorTickLength = 7.0f;
axisSet.yAxis.axisLabelOffset = 3.0f;
In this large chunk of code, we are setting up various axes properties (all of which are pretty much self explanatory). There are already a huge number of properties that you can set on axes, and that number is only going to grow as Core Plot continues to improve.
Finally, let's add some plots:
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xSquaredPlot.identifier = @"X Squared Plot";
xSquaredPlot.dataLineStyle.lineWidth = 1.0f;
xSquaredPlot.dataLineStyle.lineColor = [CPColor redColor];
xSquaredPlot.dataSource = self;
[graph addPlot:xSquaredPlot];
CPPlotSymbol *greenCirclePlotSymbol = [CPPlotSymbol ellipsePlotSymbol];
greenCirclePlotSymbol.fill = [CPFill fillWithColor:[CPColor greenColor]];
greenCirclePlotSymbol.size = CGSizeMake(2.0, 2.0);
xSquaredPlot.defaultPlotSymbol = greenCirclePlotSymbol;
CPScatterPlot *xInversePlot = [[[CPScatterPlot alloc]
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xInversePlot.identifier = @"X Inverse Plot";
xInversePlot.dataLineStyle.lineWidth = 1.0f;
xInversePlot.dataLineStyle.lineColor = [CPColor blueColor];
xInversePlot.dataSource = self;
[graph addPlot:xInversePlot];
}
In both cases we are creating scatter plots (CPScatterPlot), although there are other XY plot types (such as CPBarPlot). The key thing here is the setting of the dataSource property - you have to set that property to whatever object is going to provide data for that plot (i.e., the one that implemented the CPPlotDataSource protocol). In this case, it is the controller itself, so we just put self. For the inverse plot, all we do is color the line blue, but for the squared plot we do a little bit extra. The scatter plot allows for markers to be put at data points, and so in this case we have a small green circle at every point.
Well, that is it! You want to see what all this work looks like? If you were coding along, you could just hit "Go", but for those that weren't, here is a screenshot:
Because that viewDidLoad function is spread across a couple code blocks and probably hard to just read (or copy), here is the CorePlotTestViewController.m file in one block:
// CorePlotTestViewController.m
// CorePlotTest
//
#import "CorePlotTestViewController.h"
@implementation CorePlotTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
graph = [[CPXYGraph alloc] initWithFrame: self.view.bounds];
CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
hostingView.hostedLayer = graph;
graph.paddingLeft = 20.0;
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 20.0;
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-6)
length:CPDecimalFromFloat(12)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-5)
length:CPDecimalFromFloat(30)];
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPLineStyle *lineStyle = [CPLineStyle lineStyle];
lineStyle.lineColor = [CPColor blackColor];
lineStyle.lineWidth = 2.0f;
axisSet.xAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.xAxis.minorTicksPerInterval = 4;
axisSet.xAxis.majorTickLineStyle = lineStyle;
axisSet.xAxis.minorTickLineStyle = lineStyle;
axisSet.xAxis.axisLineStyle = lineStyle;
axisSet.xAxis.minorTickLength = 5.0f;
axisSet.xAxis.majorTickLength = 7.0f;
axisSet.xAxis.axisLabelOffset = 3.0f;
axisSet.yAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.yAxis.minorTicksPerInterval = 4;
axisSet.yAxis.majorTickLineStyle = lineStyle;
axisSet.yAxis.minorTickLineStyle = lineStyle;
axisSet.yAxis.axisLineStyle = lineStyle;
axisSet.yAxis.minorTickLength = 5.0f;
axisSet.yAxis.majorTickLength = 7.0f;
axisSet.yAxis.axisLabelOffset = 3.0f;
CPScatterPlot *xSquaredPlot = [[[CPScatterPlot alloc]
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xSquaredPlot.identifier = @"X Squared Plot";
xSquaredPlot.dataLineStyle.lineWidth = 1.0f;
xSquaredPlot.dataLineStyle.lineColor = [CPColor redColor];
xSquaredPlot.dataSource = self;
[graph addPlot:xSquaredPlot];
CPPlotSymbol *greenCirclePlotSymbol = [CPPlotSymbol ellipsePlotSymbol];
greenCirclePlotSymbol.fill = [CPFill fillWithColor:[CPColor greenColor]];
greenCirclePlotSymbol.size = CGSizeMake(2.0, 2.0);
xSquaredPlot.defaultPlotSymbol = greenCirclePlotSymbol;
CPScatterPlot *xInversePlot = [[[CPScatterPlot alloc]
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xInversePlot.identifier = @"X Inverse Plot";
xInversePlot.dataLineStyle.lineWidth = 1.0f;
xInversePlot.dataLineStyle.lineColor = [CPColor blueColor];
xInversePlot.dataSource = self;
[graph addPlot:xInversePlot];
}
-(NSUInteger)numberOfRecords {
return 51;
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index
{
double val = (index/5.0)-5;
if(fieldEnum == CPScatterPlotFieldX)
{ return [NSNumber numberWithDouble:val]; }
else
{
if(plot.identifier == @"X Squared Plot")
{ return [NSNumber numberWithDouble:val*val]; }
else
{ return [NSNumber numberWithDouble:1/val]; }
}
}
@end
Hope you found this intro to Core Plot useful! While it is still quite young as a plotting framework, it has a lot of potential (especially since it is the first one for the iPhone). You can grab a zip file below that holds the Xcode project we built today, if you want to try it out for yourself (although you will have to grab the core plot source separately - I did not include them). If you have any questions or comments, please leave them below.
07/05/2009 - 20:09
Theres a problem with the build. coreplot.h uses wrong folder directory for its includes (the folder is source and it writes CorePlot) Also, when I build and go the app stops in debug mode and I get EXC_BAD_ACCESS. It may be due to the app I put it in. I had a project already started it is a cocoa app I made with the apple tutorial and it had a main already would that generate the error?. It would be nice to show what kind of project to start it in if its better to start with a new project and maybe to specify what to do with the main.
07/05/2009 - 22:50
I actually had to put coreplot.hg like it was for the examples I ran.
07/05/2009 - 20:23
I also had to transfer some files from the iphoneOnly folder to the Source folder.
07/05/2009 - 21:01
BTW, i was doing all the same steps but for a mac application and I changed all the iphone names for mac names
09/26/2009 - 18:16
Sorry for the newbie question:
What kind of mac osx application xcode project did you start out with to start integrating these changes to get it working on the mac rather than the iphone?
07/05/2009 - 21:24
The following line does not work...it seems defaultPlotSymbol has been removed from the latest Core-plot release:
xSquaredPlot.defaultPlotSymbol = greenCirclePlotSymbol;
07/05/2009 - 21:45
concerning that same last comment.
There are 2 problems with this. its a pointer not a var so -> should be used and secondly defaultPlotSymbol doesnt exist....only plotSymbols.
07/05/2009 - 21:51
Me again sorry.....plotSymbol being protected with getter setter methods i put this line instead :
[xSquaredPlot setPlotSymbol:greenCirclePlotSymbol];
07/05/2009 - 21:59
and finally im getting these warnings:
warning: incomplete implementation of class 'CorePlotTestViewController'
warning: method definition for '-numberOfRecordsForPlot:' not found
warning: class 'CorePlotTestViewController' does not fully implement the 'CPPlotDataSource' protocolThis is all with you example on the iphone simulator. The application still launches but I get a crash asking to send to apple
07/05/2009 - 22:05
Me again, after commenting all the code in the controlller method no more crashes but of course my screen is white so something in the code is doing it.....By the way I liked your tutorial though I learned to link static libs with it :)...dont want to be too negative for nothing
07/08/2009 - 11:45
Sorry about the compile-time problems you're having. That's the problem with a framework at this stage, the APIs tend to change rapidly. In the case of the warning you're getting, you'll need to change
in the above code to the new
definition.
The white screen you're seeing may be due to the fact that the delegate method is missing and therefore won't report back how many data points need to be plotted.
If you have additional questions, I recommend posting them to the Google Group for this project at http://groups.google.com/group/coreplot-discuss?hl=en
07/08/2009 - 13:29
Thanks for the response Brad, we will quickly get the tutorial above updated. You guys are doing an awesome job at really kicking some programming tail on core plot, keep it up.
07/08/2009 - 06:01
I am having exactly the same issues as the last post, any ideas???
07/24/2009 - 05:09
I'm getting the following; any ideas? I think i set the paths right.
Building target “CorePlotTest” of project “CorePlotTest” with configuration “Debug” — (1 error, 3 warnings)
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m: In function '-[CorePlotTestViewController viewDidLoad]':
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:60: error: request for member 'defaultPlotSymbol' in something not a structure or union
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m: At top level:
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: incomplete implementation of class 'CorePlotTestViewController'
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: method definition for '-numberOfRecordsForPlot:' not found
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: class 'CorePlotTestViewController' does not fully implement the 'CPPlotDataSource' protocol
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:60: error: request for member 'defaultPlotSymbol' in something not a structure or union
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m: At top level:
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: incomplete implementation of class 'CorePlotTestViewController'
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: method definition for '-numberOfRecordsForPlot:' not found
/Developer/upstat/core-plot/CorePlotTest/Classes/CorePlotTestViewController.m:87: warning: class 'CorePlotTestViewController' does not fully implement the 'CPPlotDataSource' protocol
Build failed (1 error, 3 warnings)
07/24/2009 - 07:07
See Brad's comment above - the CPPlotDataSource protocol has changed since I wrote this tutorial. I haven't tried to build against the latest code yet, so I don't know exactly what you have to do to fix it. But if you look at the protocol definition, it should be pretty obvious.
08/01/2009 - 15:30
I tried adding core-plot to my project using the steps above and these are the errors I"m getting
The compiling erros:
CorePlotProbes.h:No such file or directory
warnings: implicit declaration of function 'COREPLOT_LAYER_POSITION_CHANGE_ENABLED'
warnings:'CPLayer may not respond to '-className'
And for Linking errors:
i686-apple-darwin9-gcc-4.2.1: /Users/fn/Documents/iPhone/core-plot/framework/build/Debug-iphonesimulator/libCorePlot-CocoaTouch.a: No such file or directory
Any ideas?
08/02/2009 - 07:04
Farhad: You need to update from the repository, there was some dtrace stuff missing in the .xcodeproj file.
I get the same warning about "may not respond to '-className' and since warnings are treated like errors per configuration default, you should go and change that setting in the core-plot cocoa touch project file.
Another issue I'm having:
axisSet.xAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];is throwing an error, complaining axisSet would be undeclared (which is true, but why is it missing in the tutorial?)
08/02/2009 - 07:05
nvm, solution is to add:
08/03/2009 - 17:25
in the simulator works but on the real one not: any idea?
the error is: GDB: Program received signal: "SIGABRT"
08/05/2009 - 12:37
The problem is in this line:
layerHost.hostedLayer= graph;
Console throws:
*** -[NSDecimalNumber isGreaterThanOrEqualTo:]: unrecognized selector sent to instance 0x101680
2009-08-05 12:33:05.416 ChecarPlazas[1908:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDecimalNumber isGreaterThanOrEqualTo:]: unrecognized selector sent to instance 0x101680'
2009-08-05 12:33:05.506 ChecarPlazas[1908:207] Stack: (
But in the simulator everything is OK...
08/05/2009 - 17:53
Problem solved:
add the next flag to the Linker:
-all_load
suerte carnales!!
08/09/2009 - 10:25
Lazio,
Thanks for that fix. Core Plot is not working on my iPhone. As I try to become more skilled in Objective C coding, I'd like to understand how you figured out that fix? Can you guide us through the steps to determine the all_load flag was missing? It seems random but I am sure it's not.
Thanks,
Amit
08/04/2009 - 10:43
These are the errors I keep receiving when trying to compile:
Line Location MainWindow.xib:3: The 'window' outlet of 'Layer Hosting View' is connected to 'Window' but 'window' is no longer defined on CPLayerHostingView.
Line Location CPLayer.h:3: error: CPPlatformSpecificDefines.h: No such file or directory
Line Location CPPlatformSpecificCategories.h:3: error: CPLayer.h: No such file or directory
08/04/2009 - 22:51
I'm getting similar issues.. is there a resolution for this?
08/05/2009 - 09:52
I found my problem. I didn't make the include path recursive
08/04/2009 - 13:19
I'm having major issues just compiling the example code supplied in the zip file. I've downloaded core plot source and made sure all header search paths are correct. Anyone help!? Are you using The Simulator as the SDK?
Building target “CorePlot-CocoaTouch” of project “CorePlot-CocoaTouch” with configuration “Debug” — (1 error)
Checking Dependencies
error: There is no SDK with specified name or path 'Unknown Path'
error: There is no SDK with specified name or path 'Unknown Path'
Build failed (1 error)
08/04/2009 - 19:44
I'm getting the same errors as the person above...
Building target “CorePlot-CocoaTouch” of project “CorePlot-CocoaTouch” with configuration “Debug” — (1 error)
Checking Dependencies
error: There is no SDK with specified name or path 'Unknown Path'
error: There is no SDK with specified name or path 'Unknown Path'
Build failed (1 error)
I'm sure I'm being dumb but could someone please set us straight?
Thank you!
Chris.
08/04/2009 - 21:06
Forget it. I figured it out. I skipped a step in the tutorial set-up.
Thanks!
08/05/2009 - 08:32
Which step did you skip? The other guys might have skipped the same step.
08/05/2009 - 21:18
Good point...
You know, I'm not sure. I only assumed I did 'cause I went back and followed the tutorial's setup carefully from scratch and it worked. I'm known (worldwide) for skimming through the manual and getting all messed up :)
I have another question though:
Has anyone seen the view invert when closing the example app running in the iPhone simulator? I'm actually seeing it in all the example iPhone projects. Anyone know what the deal is there? I love the API, but, I'm not sure I want to use it in my apps unless I can get that (very minor) issue resolved. For all I know, it's something I'm doing, but, I don't think so as I didn't edit any of the code...BTW - I'm using the 2.2.1 SDK.
Great Job, Guys!
Chris.
08/06/2009 - 09:39
Chris if you can please figure out what you changed that would help a ton! I've followed the tutorial about 5 times now. I get different errors whether I use the Simulator, Project Settings, or Debug vs. Release modes to build and Go.
If I use Simulator and Debug, my first error is:
error: CPPlatformSpecificDefines.h: No such file or directory
error: CPLayer.h No such file or directory.
Help Please!!!
08/06/2009 - 14:26
OK...
Here's what I did, exactly...
1) installed Mercurial (http://www.selenic.com/mercurial/wiki/)
2) Cloned the code base (hg clone http://core-plot.googlecode.com/hg/ core-plot)
3) Grabbed the Sample Project from this Tutorial (http://www.switchonthecode.com/sites/default/files/713/source/SOTC-CorePlotTest.zip)
4) Went through the tutorial step by step. Obviously (or maybe not), the tutorial project is setup to use paths to the core-plot installation location on the tutorial developer's machine. I installed the core-plot framework at /Users/mycompname/ so when I added/edited the compiler flags I referenced my install location. (e.g. the HEADER_SEARCH_PATHS = /Users/mycompname/core-plot/framework/**) w/ recursive setting ON).
My dev envorinment looks like this:
computer - intel MacBook pro (5 months old)
iPhone SDK - 2.2.1
Project Target - iPhone Simulator 2.2.1 DEBUG
I don't know what else to say.
It sounds like your paths are setup all the way. Especially since you get different errors for different targets...as unless you have identical global project/target settings for all you builds.
I hope this helps you. I know how frustrating this can be.
My suggestion is to start from scratch. Do what I outlined (with very special attention paid to following the tuorials step for edit the settings for the TARGET and the PROJECT...they're very different). Do that and get back to us/me...we'll get you sorted out...then you can help the next guy/gal :)
Peace and cars that run on chicken grease!
Chris.
11/12/2009 - 12:41
Hi!
I was getting this same error. But doing the recursive thing (and paying attention to the TARGET and PROJECT settings) got me going....to the next error (which is better than nothing).
I imported "CorePlot-CocoaTouch.h" in my ViewController, and now I am getting the following error:
"CorePlot-CocoaTouch.h: No such file or directory"
I am at a lost...
Can you help?
Thanks in Advance!
12/28/2009 - 17:46
You forgot to tick the "Recursive" checkbox when you added the path to core-plot in the "Header Search Paths" in the build properties.
08/06/2009 - 14:27
I meant = "It sounds like your paths AREN'T setup all the way."
08/08/2009 - 01:07
*** -[UIView setHostedLayer:]: unrecognized selector sent to instance 0xf1e350
2009-08-08 01:03:00.588 FTPPro[14161:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView setHostedLayer:]: unrecognized selector sent to instance 0xf1e350'
Any ideas?
08/08/2009 - 01:51
Interface Builder error.
I did not set the class name of the view correctly. Fat fingered CPlayer instead of CPLayer...
If you see that error, you know where to go.
02/08/2010 - 21:45
im still getting this error...im unable to set up the view outlet in the Layer Hosting View (view) to the FIle's Owner outlet and vv...it just wont let me...why?
03/05/2010 - 10:42
if you add .h files from core-plot to your project you will not have this crash
08/14/2009 - 04:00
Great job!!! Thank you.
It works with a few modifications.
Complete code looks like this:
return 51;
}
-(NSNumber *)numberForPlot:(CPPlot *)plot
field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index
{
double val = (index/5.0)-5;
if(fieldEnum == CPScatterPlotFieldX)
{ return [NSNumber numberWithDouble:val]; }
else
{
if(plot.identifier == @"X Squared Plot")
{ return [NSNumber numberWithDouble:val*val]; }
else
{ return [NSNumber numberWithDouble:1/val]; }
}
}
- (void)viewDidLoad {
[super viewDidLoad];
graph = [[CPXYGraph alloc] initWithFrame: self.view.bounds];
self.view = [[CPLayerHostingView alloc]initWithFrame:[UIScreen mainScreen].bounds];
CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
hostingView.hostedLayer = graph;
graph.paddingLeft = 20.0;
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 20.0;
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-6)
length:CPDecimalFromFloat(12)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-5)
length:CPDecimalFromFloat(30)];
CPLineStyle *lineStyle = [CPLineStyle lineStyle];
lineStyle.lineColor = [CPColor blackColor];
lineStyle.lineWidth = 2.0f;
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
axisSet.xAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.xAxis.minorTicksPerInterval = 4;
axisSet.xAxis.majorTickLineStyle = lineStyle;
axisSet.xAxis.minorTickLineStyle = lineStyle;
axisSet.xAxis.axisLineStyle = lineStyle;
axisSet.xAxis.minorTickLength = 5.0f;
axisSet.xAxis.majorTickLength = 7.0f;
axisSet.xAxis.axisLabelOffset = 3.0f;
axisSet.yAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
axisSet.yAxis.minorTicksPerInterval = 4;
axisSet.yAxis.majorTickLineStyle = lineStyle;
axisSet.yAxis.minorTickLineStyle = lineStyle;
axisSet.yAxis.axisLineStyle = lineStyle;
axisSet.yAxis.minorTickLength = 5.0f;
axisSet.yAxis.majorTickLength = 7.0f;
axisSet.yAxis.axisLabelOffset = 3.0f;
CPScatterPlot *xSquaredPlot = [[[CPScatterPlot alloc]
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xSquaredPlot.identifier = @"X Squared Plot";
xSquaredPlot.dataLineStyle.lineWidth = 1.0f;
xSquaredPlot.dataLineStyle.lineColor = [CPColor redColor];
xSquaredPlot.dataSource = self;
[graph addPlot:xSquaredPlot];
CPPlotSymbol *greenCirclePlotSymbol = [CPPlotSymbol ellipsePlotSymbol];
greenCirclePlotSymbol.fill = [CPFill fillWithColor:[CPColor greenColor]];
greenCirclePlotSymbol.size = CGSizeMake(2.0, 2.0);
[xSquaredPlot setPlotSymbol:greenCirclePlotSymbol];
CPScatterPlot *xInversePlot = [[[CPScatterPlot alloc]
initWithFrame:graph.defaultPlotSpace.bounds] autorelease];
xInversePlot.identifier = @"X Inverse Plot";
xInversePlot.dataLineStyle.lineWidth = 1.0f;
xInversePlot.dataLineStyle.lineColor = [CPColor blueColor];
xInversePlot.dataSource = self;
[graph addPlot:xInversePlot];
}
08/19/2009 - 14:30
Nice tutorial...thanks!
08/28/2009 - 09:26
Hello,
I have got 2 errors when i try to compile :
* for x and y axis
axisSet.xAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
--> error : incompatible type for argument 1 of 'setMajorIntervalLenght'
axisSet.yAxis.majorIntervalLength = [NSDecimalNumber decimalNumberWithString:@"5"];
--> error : incompatible type for argument 1 of 'setMajorIntervalLenght'
Anyway I commented out these two lines to test. The build succed but unfortunatly when i run the app it gives me the following error :
dyld: Library not loaded: /System/Library/Frameworks/UIKit.framework/UIKit
Referenced from: /Users/yyy/iphone/testCorePlot/build/Debug-iphonesimulator/testCorePlot.app/testCorePlot
Reason: image not found
I'm new at objective-c and xcode it's certainly a simple step i forgot (i hope), so if someone has an idea i will be very happy ^^
regards
08/30/2009 - 22:06
Just call the decimalValue method:
axisSet.yAxis.majorIntervalLength = [[NSDecimalNumber decimalNumberWithString:@"5"] decimalValue];
08/31/2009 - 11:15
thank you gfwalters for reply but i found another way on core-plot google group discuss (http://groups.google.com/group/coreplot-discuss/browse_thread/thread/b4ccaedad834eb9e) there are a lot of information here.
axisSet.xAxis.majorIntervalLength = CPDecimalFromFlot(5.0);
it works for me :)
09/01/2009 - 21:57
Summary of what I did to get this to work on both the simulator and the device:
http://alanduncan.net/index.php?q=node/22
09/05/2009 - 07:03
Hi Alan,
How can i customize the axis label.
I want to have the month name (Jan, Feb, Mar...) & so on in the X-Axis.
When i set the axisLabelingPolicy is equal to CPAxisLabelingPolicyNone & try to create my own axis labels, I get the following error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFArray allObjects]: unrecognized selector sent to instance 0xe9b6c0'.
09/06/2009 - 07:39
>axisSet.xAxis.majorIntervalLength = CPDecimalFromFlot(5.0);
Should be,
axisSet.xAxis.majorIntervalLength = CPDecimalFromFloat(5.0);
Got it working in the simulator now and will try it on the device shortly.
09/06/2009 - 07:53
Yeah - the "-all_load" flag made it run on the device too. :)
09/26/2009 - 18:19
Hi Brad et al. Thanks for your tutorial. It was very helpful and descriptive.
I got the basic plot feature working on the iphone simulator. Could anyone point out how I could possibly integrate thse changes to create an interactive plotting application on the mac using the core plot framework?
TIA, cheers!
11/23/2009 - 06:39
Hi,
I have study this example and work fine, only my problem is that label not appear in te axis, why?
thanks for all
12/16/2009 - 22:33
can i write a word like @"ABC" on the core-plot graph?
if use core-plot example ex.CPTestApp-iPhone
can i write words on the graph?
or can i create a label on th graph?
please teach me!!
thanks!!
01/11/2010 - 21:17
Hi,
Has anyone encountered this error when compiling?
error:redefinition of typedef 'CPNativeImage'Thanks everyone!
01/26/2010 - 05:43
You might want to check that you have not included both MacOS and iPhone specific headers in the header search path.
01/26/2010 - 05:44
You've mentioned that you can include multiple PlotSpaces in a single plot. How do I assign a second PlotSpace to a single graph? Right now I only have access to the default PlotSpace.
02/06/2010 - 07:12
Hi,
I'm getting this error.
/Users/xxxx/XcodeProject/SOTC-CorePlotExample/SOTC_CorePlotExampleViewController.xib:-1:0 The 'view' outlet of 'File's Owner' is connected to 'Layer Hosting View' but 'CPLayerHostingView' is not a kind of 'UIView' as specified by the outlet type.
Help please!
Thank you!
02/08/2010 - 21:53
In the CPTestApp, ive started coding it from scratch for my own use. All is fine, but it crashes saying Unknown Class CPLayerHostingView in IB, [UIView setHostedLayer:] unrecognized selector.
In IB, i can see that the MainWIndow.xib is fine, everything identical, set up properly. But in the individual xib files, for each individual UIView, the view outlet is connected to files owner but in yellow and the alert reads:
The view outlet of Files Owner is connected to Layer Hosting View but CPLayerHostingView is not a kind of UIView as specified by the outlet type...
any ideas? Ive tried starting the file from scratch again but i get the same error.
02/09/2010 - 12:03
i got it to work....ok, i added the -all_load -ObjC flag in the Target>Settings....I think this is where everyone gets confused...
There are 2 places where to put the other link and header search paths, in Project Settings and in Target Settings...I found these following things confusing:
1) where to add the Header Search Paths &IF Recursive or not &IF framework/ &OR framework/iPhoneonly &OR framework/Source &IF to check Always Search User Paths or not.
2) where to add the Other Links &IF to check Link with Std Libraries or Not
thx
mars
www.santiapps.com
02/26/2010 - 21:57
Has anyone figured out this issue:
/Users/ghegazi/Documents/SOTC_CorePlotTest/SOTC_CorePlotTestViewController.xib:-1:0 The 'view' outlet of 'File's Owner' is connected to 'Layer Hosting View' but 'CPLayerHostingView' is not a kind of 'UIView' as specified by the outlet type.
I got everything else right.
03/05/2010 - 17:21
I download the code, and run it on my mac.
I got the following errors:
error: incompatible type for argument 1 of 'setMajorIntervalLength:'
error: request for member 'axisLabelOffset' in something not a structure or union
error: incompatible type for argument 1 of 'setMajorIntervalLength:'
error: incompatible type for argument 1 of 'setMajorIntervalLength:'
and etc 7 errors. Anyone have any ideas what's going wrong here??
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.