使用Core Plot绘制iPhone上的日期 X 轴

15
我手头有一个包含NSDateNSNumber值的字典数组,我想在X轴上绘制日期。为了绘图,我需要提供xRanges以使用一些小数值进行绘制。我不明白如何将NSDate值提供给xRange(低位和长度)。
此外,在这个方法中应该有什么:
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
我是说我的日期值会以NSNumber形式返回?我认为我应该在那里使用一些时间间隔,但应该是什么确切的转换? 有人能解释一下在x轴上绘制日期所需的确切要求吗?
我正在将图绘制在视图的一半。

嘿,xmax,我在我的项目中也在做同样的事情。你找到了任何解决方法吗? - sandy
我卡在一个问题上,就像你遇到的那样。你能指导我在这种情况下该做什么吗? - Iqbal Khan
注意,现代iOS中,苹果推荐使用日期格式化程序的唯一方法是:https://dev59.com/uWAf5IYBdhLWcg3wUBX4#42370648 - Fattie
2个回答

36

请看,DatePlot已经在iOS上运行。别忘了检查它是否正确。

- (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;
}

嘿,这对我帮助很大。我只是想不出如何确定哪个NSTimeInterval上写了x轴的值? - JonasG
1
嗨,@zambono,符号'plotData'的类型是什么?我想知道它的定义。 - Sabbath
1
使用CorePlot 1.1,您不再需要反转y轴。如果您将“verticalFlip”行删除,则上述代码将起作用。 - Ben Clayton
同样重要的是在x值中使用NSNumber,而不是NSDate。 - Stan
当跨越夏令时时,将oneDay视为等于246060是否会引起问题? - dave adelson

8

请查看示例文件夹中的DatePlot程序。它展示了如何将轴标签格式化为日期。


实际上,我正在遵循那个例子。但是使用那个技巧来绘制图形,但是图形不可见。因为它不在范围内或提供值时出现了问题。 实际上,我的数据包含过去3到6个月的日期。当将NSdate转换为等效的NSDecimalNumber时,我不知道应该提供什么参考日期。 而且我对plotSpace.xRange感到困惑。我应该提供什么?我的意思是,我如何从我的数据源计算要提供给xRange的日期范围? - xmax
还有一件事是,我无法在核心绘图库的股票图示例中正确显示x轴上的日期。 如果我要在核心绘图库的股票图示例中绘制x轴,应该怎么做呢? - xmax
2
参考日期可以是任何你想要的日期。它定义了轴的零点。轴范围的起始位置是轴上第一个日期和参考日期之间的差值(以秒为单位)。范围长度是范围的总秒数(一天有86400秒)。 - Eric Skroch
谢谢您的建议。我按照您提到的方法进行了操作,现在它已经以应有的方式绘制出图形。 但是我遇到的问题是,我想在x轴上显示日期标签,但目前没有显示。我将masksToBorder属性设置为NO,您能告诉我问题可能出在哪里吗..? 我还为x轴提供了CPdateFormatter。 - xmax
将 dateplot 从 OSX 转换到 iOS 时,当向图表提供数据时,会出现错误访问的问题。 - zambono
这是一个NSMutableArray,它只是对NewData的保留指针,NewData包含具有x和y值的字典对象。 - zambono

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接