委托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 或类似的东西......)