2012-01-26 152 views
2

我目前正在嘗試使用核心圖庫來繪製通過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; 
} 

回答

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

回覆:1.我現在將它們存儲爲實例變量,但在編譯時遇到錯誤並重新加載數據。我已更新我的Dropbox zip以反映這些更改。 – James