2012-01-26 3 views
2

В настоящее время я пытаюсь использовать библиотеку основного сюжета для графического отображения некоторых данных, которые я получаю через 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; 
} 

ответ

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; 
    } 
    
+0

1. Они должны содержать одинаковое число участков, редко может отличаться на один или два. 2. Можете ли вы расширить это? 3. Внедрил ваши идеи источников данных, но не смог отобразить любой график. – James

+0

Re: 1. Я теперь храню их как переменные экземпляра, но испытываю ошибки при компиляции и перезагружает данные. Я обновил свой почтовый ящик Dropbox, чтобы отразить эти изменения. – James

Смежные вопросы