1

委托numberForPlot被正确调用,返回的值为 NSNumbers,例如 40。(Y 轴范围为 0-100 -> 百分比。)

如您在下面的屏幕截图中所见,x 轴工作正常。

在此处输入图像描述

编码

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSLog(@"Schedule: %@", self.schedule.name);

    self.plotData = [NSMutableArray array];
    NSSet *logs = self.schedule.logs;

    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dateTimeOriginal" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    NSArray *sortedLogsByDate = [logs sortedArrayUsingDescriptors:sortDescriptors];

    NSDate *oldestDate = ((LogEntry *)[sortedLogsByDate objectAtIndex:0]).dateTimeOriginal;
    NSDate *newestDate = ((LogEntry *)[sortedLogsByDate lastObject]).dateTimeOriginal;

    NSLog(@"First: %@", oldestDate);
    NSLog(@"Last: %@", newestDate);

    NSInteger intervalInSeconds = 60*60*24*7; //One Week

    NSInteger oldestDateInSeconds = [oldestDate timeIntervalSince1970];
    NSInteger newestDateInSeconds = [newestDate timeIntervalSince1970];

    NSInteger numberOfWeeks = (newestDateInSeconds - oldestDateInSeconds + intervalInSeconds - 1)/intervalInSeconds; //Integer division and round up (faster then converting to floats and round()

    NSLog(@"Number of weeks: %d", numberOfWeeks);

    NSDate *previousDate = oldestDate;
    for (int i = 1; i < numberOfWeeks+1; i++) {
        NSDate *nextDate = [previousDate dateByAddingTimeInterval:i*intervalInSeconds]; //Add one week

        NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"(dateTimeOriginal >= %@) AND (dateTimeOriginal <= %@)", previousDate, nextDate];
        NSSet *logsInThisPeriod = [logs filteredSetUsingPredicate:datePredicate];

        if (logsInThisPeriod.count > 0) {
            //Get logs between previous and next date
            NSPredicate *onTimePredicate = [NSPredicate predicateWithFormat:@"status == %@", @"onTime"];
            NSSet *onTime = [logs filteredSetUsingPredicate:onTimePredicate];

            NSPredicate *postponedPredicate = [NSPredicate predicateWithFormat:@"status == %@", @"postPoned"];
            NSSet *postponed = [logs filteredSetUsingPredicate:postponedPredicate];

            NSPredicate *missedPredicate = [NSPredicate predicateWithFormat:@"status == %@", @"missed"];
            NSSet *missed = [logs filteredSetUsingPredicate:missedPredicate];

            NSInteger onTimeCount = onTime.count;
            NSInteger postponedCount = postponed.count;
            NSInteger missedCount = missed.count;
            NSInteger total = onTimeCount + postponedCount + missedCount;

            NSInteger onTimePercentage = onTimeCount*100/total;
            NSInteger postponedPercentage = postponedCount*100/total;
            NSInteger missedPercentage = missedCount*100/total;

            NSDictionary *dataPoint = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInteger:onTimePercentage], @"onTime", [NSNumber numberWithInteger:postponedPercentage], @"postponed", [NSNumber numberWithInteger:missedPercentage], @"missed", nextDate, @"date", nil];
            [self.plotData addObject:dataPoint];
        }
        else {
            NSMutableDictionary *previousDictionary = [[self.plotData lastObject] mutableCopy];
            [previousDictionary setObject:nextDate forKey:@"date"];
            [self.plotData addObject:previousDictionary];
        }

        previousDate = nextDate;
    }

    //Create host view
    self.hostingView = [[CPTGraphHostingView alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
    [self.view addSubview:self.hostingView];

    // Create graph from theme
    graph = [(CPTXYGraph *)[CPTXYGraph alloc] initWithFrame:CGRectZero];
    CPTTheme *theme = [CPTTheme themeNamed:kCPTDarkGradientTheme];
    [graph applyTheme:theme];
    [self.hostingView setHostedGraph:self.graph];

    // Setup scatter plot space
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
    NSTimeInterval xLow       = 0.0f;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(xLow) length:CPTDecimalFromFloat((newestDateInSeconds - oldestDateInSeconds))];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(100.0)];
    plotSpace.allowsUserInteraction = YES;

    // Axes
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *x          = axisSet.xAxis;
    x.majorIntervalLength         = CPTDecimalFromFloat((float)intervalInSeconds);
    x.minorTicksPerInterval       = 0;
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateStyle = kCFDateFormatterShortStyle;
    CPTTimeFormatter *timeFormatter = [[CPTTimeFormatter alloc] initWithDateFormatter:dateFormatter];
    timeFormatter.referenceDate = oldestDate;
    x.labelFormatter            = timeFormatter;

    CPTXYAxis *y = axisSet.yAxis;
    y.majorIntervalLength         = CPTDecimalFromString(@"10.0");
    y.minorTicksPerInterval       = 1;

    //Ontime plot
    CPTScatterPlot *onTimePlot = [[CPTScatterPlot alloc] init];
    onTimePlot.identifier = @"onTimePlot";

    CPTMutableLineStyle *onTimeLineStyle = [onTimePlot.dataLineStyle mutableCopy];
    onTimeLineStyle.lineWidth                = 3.f;
    onTimeLineStyle.lineColor                = [CPTColor greenColor];
    onTimePlot.dataLineStyle = onTimeLineStyle;

    onTimePlot.dataSource = self;
    [graph addPlot:onTimePlot];

    // Put an area gradient under the plot above
    CPTColor *areaColor = [CPTColor colorWithComponentRed:0.3 green:1.0 blue:0.3 alpha:0.3];
    CPTGradient *areaGradient = [CPTGradient gradientWithBeginningColor:areaColor endingColor:[CPTColor clearColor]];
    areaGradient.angle = -90.0f;
    CPTFill *areaGradientFill = [CPTFill fillWithGradient:areaGradient];
    onTimePlot.areaFill = areaGradientFill;
    onTimePlot.areaBaseValue = CPTDecimalFromString(@"1.75");

    //Postponed plot
    CPTScatterPlot *postponedPlot = [[CPTScatterPlot alloc] init];
    postponedPlot.identifier = @"postponedPlot";

    CPTMutableLineStyle *postponedLineStyle = [postponedPlot.dataLineStyle mutableCopy];
    postponedLineStyle.lineWidth                 = 3.f;
    postponedLineStyle.lineColor                 = [CPTColor orangeColor];
    postponedPlot.dataLineStyle = postponedLineStyle;

    postponedPlot.dataSource = self;
    [graph addPlot:postponedPlot];

    //Missed plot
    CPTScatterPlot *missedPlot = [[CPTScatterPlot alloc] init];
    missedPlot.identifier = @"missedPlot";

    CPTMutableLineStyle *missedLineStyle = [missedPlot.dataLineStyle mutableCopy];
    missedLineStyle.lineWidth                = 3.f;
    missedLineStyle.lineColor                = [CPTColor redColor];
    missedPlot.dataLineStyle = missedLineStyle;

    missedPlot.dataSource = self;
    [graph addPlot:missedPlot];
}

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return self.plotData.count;
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSDictionary *plotPoint = [self.plotData objectAtIndex:index];

    if (plot.identifier == @"onTimePlot") {
        NSNumber *onTime = [plotPoint valueForKey:@"onTime"];
        return onTime;
    }
    else if (plot.identifier == @"postponedPlot") {
        NSNumber *postponed = [plotPoint valueForKey:@"postponed"];
        return postponed;
    }
    else if (plot.identifier == @"missedPlot") {
        NSNumber *missed =  [plotPoint valueForKey:@"missed"];
        return missed;
    }
    else {
        return nil;
    }
}

更新 这并没有改变任何事情:

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSDictionary *plotPoint = [self.plotData objectAtIndex:index];

    NSNumber *num = nil;

    // FieldEnum determines if we return an X or Y value.
    if ( fieldEnum == CPTScatterPlotFieldX )
    {
        return [NSNumber numberWithFloat:[[plotPoint valueForKey:@"date"] timeIntervalSince1970]];
    }
    else    // Y-Axis
    {
        if (plot.identifier == @"onTimePlot") {
            num = [plotPoint valueForKey:@"onTime"];
        }
        else if (plot.identifier == @"postponedPlot") {
            num = [plotPoint valueForKey:@"postponed"];
        }
        else if (plot.identifier == @"missedPlot") {
            num =  [plotPoint valueForKey:@"missed"];
        }

        return [NSNumber numberWithFloat:[num floatValue]];
    }
}

Bonusquestion:如何使轴标签静态并让绘图区域可滚动?如何更改 y 轴标签的“视口”?(我希望在启动时可见 0-100,现在是 20-80 或类似的东西......)

4

1 回答 1

0

我认为你在 numberForPlot:field:recordIndex 中需要这样的东西:

if (plot.identifier == @"onTimePlot")
{
    // FieldEnum determines if we return an X or Y value.
    if ( fieldEnum == CPTScatterPlotFieldX )
    {
        return [NSNumber numberWithFloat:point.x];
    }
    else    // Y-Axis
    {
        return [NSNumber numberWithFloat:point.y];
    }
}

您必须通过该方法返回一次 X 值,下一次返回 Y 值。

于 2012-05-08T20:54:00.730 回答