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.

iOS Dev
  • 4,143
  • 5
  • 30
  • 58
xmax
  • 231
  • 1
  • 3
  • 8
  • Hey xmax I am doing the same thing in my project. Have you found any workaround for the same? – sandy Jun 29 '10 at 11:19
  • i am stuck at problem that you face. so will you guide me what u do in that situation. – Iqbal Khan Jun 21 '11 at 12:14
  • NOTE, one thing, in modern iOS, the only way recommended by Apple to use a date formatter is: https://stackoverflow.com/a/42370648/294884 – Fattie Jul 28 '17 at 13:52

2 Answers2

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;
}
zambono
  • 1,397
  • 1
  • 17
  • 26
  • 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? – JonasG Oct 03 '11 at 16:03
  • 1
    Hi , @zambono , what is the type of the symbol 'plotData' ? I want to know the definition of it . – Sabbath Jul 20 '12 at 06:39
  • 1
    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. – Ben Clayton Feb 15 '13 at 11:15
  • Also it is important to use NSNumber in x value, not NSDate. – Stan May 11 '13 at 12:45
  • doesn't the use of oneDay as equal to 24*60*60 cause problems when crossing daylight savings time? – dave adelson Aug 21 '15 at 17:19
8

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

Eric Skroch
  • 27,381
  • 3
  • 29
  • 36
  • 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..? – xmax Jun 09 '10 at 07:17
  • 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..? – xmax Jun 09 '10 at 09:23
  • 2
    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). – Eric Skroch Jun 09 '10 at 11:35
  • 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.. – xmax Jun 09 '10 at 15:36
  • converting dateplot from osx to ios gives me bad access error , but only when giving data to the chart. – zambono Aug 08 '11 at 13:27
  • it's an NSMutableArray, it's just a retained pointer to NewData, neData contains dictionary objects with x and y values – zambono Jul 27 '12 at 15:11