Using core plot for iPhone, drawing date on x axis
Asked Answered
I

2

15

I have available an array of dictionary that contains NSDate and NSNumber values. I wanted to plot date on X axis. For plotting I need to supply xRanges to plot with some decimal values. I don't understand how can I supply NSDate values to xRange (low and length).

And what should be there in this method:

-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index

I mean how my date value will be returned as NSNumber? I think I should use some interval over there, but what should be the exact conversion? Can any one explain me what are the exact requirement to plot the date on xAxis?

I am plotting my plot in half of the view.

Inapprehensible answered 8/6, 2010 at 14:46 Comment(3)
Hey xmax I am doing the same thing in my project. Have you found any workaround for the same?Intercessory
i am stuck at problem that you face. so will you guide me what u do in that situation.Polygyny
NOTE, one thing, in modern iOS, the only way recommended by Apple to use a date formatter is: https://mcmap.net/q/127867/-how-can-i-convert-string-date-to-nsdateContractile
F
36

Here you go, DatePlot working on iOS. Don't forget to check it as correct.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    // If you make sure your dates are calculated at noon, you shouldn't have to 
    // worry about daylight savings. If you use midnight, you will have to adjust
    // for daylight savings time.
    NSDate *refDate = [NSDate dateWithTimeIntervalSinceReferenceDate:31556926 * 10];
    NSTimeInterval oneDay = 24 * 60 * 60;

    // Invert graph view to compensate for iOS coordinates
    CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1,-1);
    self.view.transform = verticalFlip;

     // allocate the graph within the current view bounds
    graph = [[CPTXYGraph alloc] initWithFrame: self.view.bounds];

    // assign theme to graph
    CPTTheme *theme = [CPTTheme themeNamed:kCPTDarkGradientTheme];
    [graph applyTheme:theme];

    // Setting the graph as our hosting layer
    CPTGraphHostingView *hostingView = [[CPTGraphHostingView alloc] initWithFrame:self.view.bounds];

    [self.view addSubview:hostingView];

    hostingView.hostedGraph = graph;

    graph.paddingLeft = 20.0;
    graph.paddingTop = 20.0;
    graph.paddingRight = 20.0;
    graph.paddingBottom = 150.0;

    // setup a plot space for the plot to live in
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
    NSTimeInterval xLow = 0.0f;
    // sets the range of x values
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(xLow)
                                                   length:CPTDecimalFromFloat(oneDay*5.0f)];
    // sets the range of y values
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) 
                                                   length:CPTDecimalFromFloat(5)];

    // plotting style is set to line plots
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.lineColor = [CPTColor blackColor];
    lineStyle.lineWidth = 2.0f;

    // X-axis parameters setting
    CPTXYAxisSet *axisSet = (id)graph.axisSet;
    axisSet.xAxis.majorIntervalLength = CPTDecimalFromFloat(oneDay);
    axisSet.xAxis.minorTicksPerInterval = 0;
    axisSet.xAxis.orthogonalCoordinateDecimal = CPTDecimalFromString(@"1"); //added for date, adjust x line
    axisSet.xAxis.majorTickLineStyle = lineStyle;
    axisSet.xAxis.minorTickLineStyle = lineStyle;
    axisSet.xAxis.axisLineStyle = lineStyle;
    axisSet.xAxis.minorTickLength = 5.0f;
    axisSet.xAxis.majorTickLength = 7.0f;
    axisSet.xAxis.labelOffset = 3.0f;

    // added for date
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    dateFormatter.dateStyle = kCFDateFormatterShortStyle;
    CPTTimeFormatter *timeFormatter = [[[CPTTimeFormatter alloc] initWithDateFormatter:dateFormatter] autorelease];
    timeFormatter.referenceDate = refDate;
    axisSet.xAxis.labelFormatter = timeFormatter;

    // Y-axis parameters setting    
    axisSet.yAxis.majorIntervalLength = CPTDecimalFromString(@"0.5");
    axisSet.yAxis.minorTicksPerInterval = 2;
    axisSet.yAxis.orthogonalCoordinateDecimal = CPTDecimalFromFloat(oneDay); // added for date, adjusts y line
    axisSet.yAxis.majorTickLineStyle = lineStyle;
    axisSet.yAxis.minorTickLineStyle = lineStyle;
    axisSet.yAxis.axisLineStyle = lineStyle;
    axisSet.yAxis.minorTickLength = 5.0f;
    axisSet.yAxis.majorTickLength = 7.0f;
    axisSet.yAxis.labelOffset = 3.0f;


    // This actually performs the plotting
    CPTScatterPlot *xSquaredPlot = [[[CPTScatterPlot alloc] init] autorelease];

    CPTMutableLineStyle *dataLineStyle = [CPTMutableLineStyle lineStyle];
    //xSquaredPlot.identifier = @"X Squared Plot";
    xSquaredPlot.identifier = @"Date Plot";

    dataLineStyle.lineWidth = 1.0f;
    dataLineStyle.lineColor = [CPTColor redColor];
    xSquaredPlot.dataLineStyle = dataLineStyle;
    xSquaredPlot.dataSource = self;

    CPTPlotSymbol *greenCirclePlotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
    greenCirclePlotSymbol.fill = [CPTFill fillWithColor:[CPTColor greenColor]];
    greenCirclePlotSymbol.size = CGSizeMake(2.0, 2.0);
    xSquaredPlot.plotSymbol = greenCirclePlotSymbol;  

    // add plot to graph
    [graph addPlot:xSquaredPlot];

    // Add some data
    NSMutableArray *newData = [NSMutableArray array];
    NSUInteger i;
    for ( i = 0; i < 5; i++ ) {
        NSTimeInterval x = oneDay*i;
        id y = [NSDecimalNumber numberWithFloat:1.2*rand()/(float)RAND_MAX + 1.2];
        [newData addObject:
         [NSDictionary dictionaryWithObjectsAndKeys:
          [NSDecimalNumber numberWithFloat:x], [NSNumber numberWithInt:CPTScatterPlotFieldX], 
          y, [NSNumber numberWithInt:CPTScatterPlotFieldY], 
          nil]];
        NSLog(@"%@",newData);
    }
    plotData = [newData retain];

}

#pragma mark - Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return plotData.count;
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSDecimalNumber *num = [[plotData objectAtIndex:index] objectForKey:[NSNumber numberWithInt:fieldEnum]];
    return num;
}
Frowsy answered 8/8, 2011 at 13:35 Comment(5)
hey, this helped me a lot. I just can't figure out, how to actually decide which value is written on the x axis for which NSTimeInterval?Botulism
Hi , @Frowsy , what is the type of the symbol 'plotData' ? I want to know the definition of it .Asturias
With CorePlot 1.1, you don't need to invert the y-axis any more. Above code works if you take the 'verticalFlip' lines out.Lignify
Also it is important to use NSNumber in x value, not NSDate.Kroo
doesn't the use of oneDay as equal to 24*60*60 cause problems when crossing daylight savings time?Aligarh
D
8

Take a look at the DatePlot program in the examples folder. It shows how to format axis labels as dates.

Deltoid answered 9/6, 2010 at 2:28 Comment(6)
Infact I am following that example. but using that trick to plot the graph but graph is not visible. as It's not under range or something wrong with providing values. actually, my data contains the date with past 3 to 6 months. I am not getting what exactly I should provide reference date when converting NSdate to equivalent NSDecimalNumber. And I am confused over plotSpace.xRange. what I should supply.? I mean how can i calculate the range of dates to supply for xRange from my datasource..?Inapprehensible
And one more thing is that, I am not able to display date properly on xAxis, with the example stock plot in coreplot. if I have to draw xAxis on core plot StockPlot example, then how it would be..?Inapprehensible
The reference date can be anything you want. It defines the zero point for the axis. The starting location for the axis range is the difference between your first date on the axis and the reference date, in seconds. The range length is the length of the range in seconds (there are 86400 seconds in a day).Deltoid
Thanks for your suggestion. I did it the way you mentioned and it is plotting graph the way it should. But the problem here I am getting is I want to show date label on xAxis. and It is not displaying currently. I setted masksToBorder property to NO. can you tell me where could be the problem..? I provided CPdateFormatter for xAxis as well..Inapprehensible
converting dateplot from osx to ios gives me bad access error , but only when giving data to the chart.Frowsy
it's an NSMutableArray, it's just a retained pointer to NewData, neData contains dictionary objects with x and y valuesFrowsy

© 2022 - 2024 — McMap. All rights reserved.