основной сюжет, невозможно построить два графика - PullRequest
2 голосов
/ 26 января 2012

В настоящее время я пытаюсь использовать библиотеку 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 Ответ

5 голосов
/ 26 января 2012

Вот несколько вещей, которые выскочили на меня в вашем коде:

  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;
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...