核心情节,无法绘制两个图

时间:2012-01-26 02:09:00

标签: iphone ios ipad charts core-plot

我目前正在尝试使用核心图库来绘制我通过JSON获得的一些数据。我试图在同一个图表上绘制两个图,但我无法实现这一点。当我只绘制一个图表时,它可以正常工作。

下面是我使用核心图库的散点图代码。

#pragma mark -
#pragma mark Plot construction methods

- (void)constructScatterPlot
{
    NSMutableArray *appleContentArray = [NSMutableArray arrayWithCapacity:270];
    NSMutableArray *googleContentArray = [NSMutableArray arrayWithCapacity:270];

    NSData *stocks = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://d1sz0kydzogekx.cloudfront.net/stocks.txt"]];
    NSInputStream *stockStream = [[NSInputStream alloc] initWithData:stocks];
    [stockStream open];

    NSUInteger i;
    i = 1;

    if (stockStream) {
        NSError *parseError = nil;
        id jsonObject = [NSJSONSerialization JSONObjectWithStream:stockStream options:NSJSONReadingAllowFragments error:&parseError];

        if ([jsonObject respondsToSelector:@selector(objectForKey:)]) {
            for (NSDictionary *stock in [jsonObject objectForKey:@"stocks"]) {
                if ([[stock objectForKey:@"stock"] isEqualToString:@"AAPL"]){
                    id x = [NSNumber numberWithInt:i];
                    id y = [stock objectForKey:@"close"];

                    [appleContentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]];
                }

                if ([[stock objectForKey:@"stock"] isEqualToString:@"GOOG"]){
                    id x = [NSNumber numberWithInt:i];
                    id y = [stock objectForKey:@"close"];

                    [googleContentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]];
                }

                i++;
            }
        }

    } else {
        NSLog(@"Failed to open stream.");
    }

    // Create graph from theme
    graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
    CPTTheme *theme = [CPTTheme themeNamed:kCPTPlainBlackTheme];
    [graph applyTheme:theme];
    scatterPlotView.hostedGraph = graph;

    graph.paddingLeft = 0;
    graph.paddingTop = 0.0;
    graph.paddingRight = 0;
    graph.paddingBottom = 0;

    // Setup plot space
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
    plotSpace.allowsUserInteraction = YES;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(-20.0) length:CPTDecimalFromFloat(260.0)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(150.0) length:CPTDecimalFromFloat(400.0)];

    // Axes
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *x = axisSet.xAxis;
    x.majorIntervalLength = CPTDecimalFromString(@"1000");
    x.orthogonalCoordinateDecimal = CPTDecimalFromString(@"2");
    x.minorTicksPerInterval = 2;
    NSArray *exclusionRanges = [NSArray arrayWithObjects:
                                [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(1.99) length:CPTDecimalFromFloat(0.02)], 
                                [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.99) length:CPTDecimalFromFloat(0.02)],
                                [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(2.99) length:CPTDecimalFromFloat(0.02)],
                                nil];
    x.labelExclusionRanges = exclusionRanges;

    CPTXYAxis *y = axisSet.yAxis;
    y.majorIntervalLength = CPTDecimalFromString(@"50");
    y.orthogonalCoordinateDecimal = CPTDecimalFromString(@"2");
    y.minorTicksPerInterval = 2;

    exclusionRanges = [NSArray arrayWithObjects:
                       [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(1.99) length:CPTDecimalFromFloat(0.02)], 
                       [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.99) length:CPTDecimalFromFloat(0.02)],
                       [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(3.99) length:CPTDecimalFromFloat(0.02)],
                       nil];
    y.labelExclusionRanges = exclusionRanges;

    // Create a green Apple plot area
    CPTScatterPlot *appleLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
    appleLinePlot.identifier = @"Green Plot";

    CPTMutableLineStyle *appleLineStyle = [[appleLinePlot.dataLineStyle mutableCopy] autorelease];

    appleLineStyle.lineWidth = 2.0;
    appleLineStyle.lineColor = [CPTColor greenColor];

    appleLinePlot.dataLineStyle = appleLineStyle;
    appleLinePlot.opacity = 0.0f;
    appleLinePlot.cachePrecision = CPTPlotCachePrecisionDecimal;

    // Create a red Google plot area
    CPTScatterPlot *googleLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
    googleLinePlot.identifier = @"Red Plot";

    CPTMutableLineStyle *googleLineStyle = [[googleLinePlot.dataLineStyle mutableCopy] autorelease];

    googleLineStyle.lineWidth = 2.0;
    googleLineStyle.lineColor = [CPTColor redColor];
    googleLinePlot.dataLineStyle = googleLineStyle;

    // Animate in the new plot
    CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeInAnimation.duration = 0.0f;
    fadeInAnimation.removedOnCompletion = NO;
    fadeInAnimation.fillMode = kCAFillModeForwards;
    fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0];
    [appleLinePlot addAnimation:fadeInAnimation forKey:@"animateOpacity"];
    [googleLinePlot addAnimation:fadeInAnimation forKey:@"animateOpacity"];

    appleLinePlot.cachePrecision = CPTPlotCachePrecisionDecimal;
    googleLinePlot.cachePrecision = CPTPlotCachePrecisionDecimal;

    appleLinePlot.dataSource = self;
    self.dataForPlot = appleContentArray;
    [graph addPlot:appleLinePlot];

    googleLinePlot.dataSource = self;
    self.dataForPlot = googleContentArray;
    [graph addPlot:googleLinePlot];
}

#pragma mark -
#pragma mark CPTBarPlot delegate method

-(void)barPlot:(CPTBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)index
{
    NSLog(@"barWasSelectedAtRecordIndex %d", index);
}

#pragma mark -
#pragma mark Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot 
{
    return [dataForPlot count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index 
{
    NSDecimalNumber *num = nil;

    num = [[dataForPlot objectAtIndex:index] valueForKey:(fieldEnum == CPTScatterPlotFieldX ? @"x" : @"y")];

    if ( [(NSString *)plot.identifier isEqualToString:@"Green Plot"] ) {
        if ( fieldEnum == CPTScatterPlotFieldX ) {
            num = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:[num doubleValue]];
        }

        if ( fieldEnum == CPTScatterPlotFieldY ) {
            num = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:[num doubleValue]];
        }
    }

    if ( [(NSString *)plot.identifier isEqualToString:@"Red Plot"] ) {
        if ( fieldEnum == CPTScatterPlotFieldX ) {
            num = (NSDecimalNumber *)[NSDecimalNumber numberWithDouble:[num doubleValue]];
        }
    }

    return num;
}

1 个答案:

答案 0 :(得分:5)

以下是您的代码中突然出现的一些内容:

  1. 绘图数据需要可用于数据源。最简单的方法是将两个内容数组存储在实例变量中,以便它们在整个类中可见,而不是在-constructScatterPlot方法完成后消失的局部变量中。

  2. 这两个情节总是有相同数量的情节点吗?如果没有,请检查-numberOfRecordsForPlot:中的绘图标识符,并为每个标识符返回正确的计数。

     -(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot 
     {
        if ( [(NSString *)plot.identifier isEqualToString:@"Green Plot"] ) {
           return appleContentArray.count;
        }
        else if ( [(NSString *)plot.identifier isEqualToString:@"Red Plot"] ) {
            return googleContentArray.count;
        }
        return 0;
    }
    
  3. 您的数据源可以大大简化(我的示例使用您的原始数据结构):

    -(NSNumber *)numberForPlot:(CPTPlot *)plot
                         field:(NSUInteger)fieldEnum
                   recordIndex:(NSUInteger)index 
    {
        NSArray *contentArray = nil;
    
        if ( [(NSString *)plot.identifier isEqualToString:@"Green Plot"] ) {
            contentArray = appleContentArray;
        }
        else if ( [(NSString *)plot.identifier isEqualToString:@"Red Plot"] ) {
            contentArray = googleContentArray;
        }
    
        return [[contentArray objectAtIndex:index] valueForKey:(fieldEnum == CPTScatterPlotFieldX ? @"x" : @"y")];
    }
    
  4. 您的内容数组是否包含预期值?你真的需要存储索引吗?除非你需要其他东西,否则我只是将close值存储在内容数组中而忘记字典结构。在这种情况下,数据源方法变为:

    -(NSNumber *)numberForPlot:(CPTPlot *)plot
                         field:(NSUInteger)fieldEnum
                   recordIndex:(NSUInteger)index 
    {
        NSNumber *num = nil;
    
        switch ( fieldEnum ) {
        case CPTScatterPlotFieldX:
            num = [NSNumber numberWithUnsignedInteger:index];
            break;
    
        case CPTScatterPlotFieldY:
            if ( [(NSString *)plot.identifier isEqualToString:@"Green Plot"] ) {
                num = [appleContentArray objectAtIndex:index];
            }
            else if ( [(NSString *)plot.identifier isEqualToString:@"Red Plot"] ) {
                num = [googleContentArray objectAtIndex:index];
            }
            break;
        }
    
        return num;
    }