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

下面是我使用core-plot库的散点图代码。

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

最佳答案

以下是您的代码中让我惊讶的一些事情:

  • 图数据需要可用于数据源。最简单的方法是将两个内容数组存储在实例变量中,以便它们在整个类中可见,而不是在-constructScatterPlot方法完成时消失的局部变量中。
  • 两个图是否总是具有相同数量的图点?如果不是,请在-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;
    }
    
  • 您的数据源可以大大简化(我的示例使用您的原始数据结构):
    -(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")];
    }
    
  • 您的内容数组是否包含期望值?您是否真的需要存储索引?除非您有其他需要,否则我将只将close值存储在content数组中,而无需考虑字典结构。在这种情况下,数据源方法变为:
    -(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;
    }
    
  • 关于iphone - 核心图,无法绘制两个图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9013197/

    10-13 00:22