CorePlot刷新绘图连接到表

时间:2015-07-17 15:10:05

标签: arrays xcode macos core-plot

我正在使用xCode上的核心情节,我想通过蓝牙绘制一些实时传入数据。 我使用CPTTestAPP for Mac Os X作为示例,并尝试根据我的具体情况进行调整。 前60个点是按照它应该添加的,并且由于以下未更改的代码:

-(void)setupScatterPlots
{
    static BOOL hasData = NO;

    // Create one plot that uses bindings
    CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];

    boundLinePlot.identifier = bindingsPlot;

    CPTMutableLineStyle *lineStyle = [boundLinePlot.dataLineStyle mutableCopy];
    lineStyle.miterLimit        = 1.0;
    lineStyle.lineWidth         = 2.0;
    lineStyle.lineColor         = [CPTColor redColor];
    boundLinePlot.dataLineStyle = lineStyle;

    [self.graph addPlot:boundLinePlot];
    [boundLinePlot bind:CPTScatterPlotBindingXValues toObject:self withKeyPath:@"arrangedObjects.x" options:nil];
    [boundLinePlot bind:CPTScatterPlotBindingYValues toObject:self withKeyPath:@"arrangedObjects.y" options:nil];

    // Set plot delegate, to know when symbols have been touched
    // We will display an annotation when a symbol is touched
    boundLinePlot.delegate                        = self;
    boundLinePlot.plotSymbolMarginForHitDetection = 5.0;


    if ( !hasData ) {
        // Add some initial data
        contentArray = [NSMutableArray arrayWithCapacity:100];
        for ( NSUInteger i = 0; i < 60; i++ ) {
            NSNumber *x = @(1.0 + i * 0.05);
            NSNumber *y = @(1.2 * arc4random() / (double)UINT32_MAX + 1.2);
            [contentArray addObject:@{ @"x": x,
                                       @"y": y }
            ];
        }

        self.content = contentArray;
        hasData      = YES;
    }

    // Auto scale the plot space to fit the plot data
    // Extend the y range by 10% for neatness
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
    plotSpace.allowsMomentum = YES;

    [plotSpace scaleToFitPlots:@[boundLinePlot]];
    CPTPlotRange *xRange        = plotSpace.xRange;
    CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
    [yRange expandRangeByFactor:CPTDecimalFromDouble(1.1)];
    plotSpace.yRange = yRange;

    // Restrict y range to a global range
    plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(10.0)];
    plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(5.0)];

    // set the x and y shift to match the new ranges
    CGFloat length = xRange.lengthDouble;
    self.xShift = length - 3.0;
    length      = yRange.lengthDouble;
    self.yShift = length - 2.0;
}

我正在使用一个名为insertData的方法,它看起来像这样:

-(void)insertData:(uint32 *) buf :(uint32 *) i
{

    [contentArray addObject:@{ @"x": i,
                               @"y": buf }
     ];
    NSLog(@"%@",contentArray);
    self.content = contentArray;
}

其中buf是我的传入数据。 但是当我调用insertData方法时,数据会附加到数组中,但我界面上的选项卡不会改变,情节也不会改变。

是的,有人可以帮我吗? 谢谢!

我已经尝试使用以下命令将int转换为NSNumber:

NSNumber *ni = @(*i);
NSNumber *nbuf = @(*buf);

NSNumber *ni = [NSNumber numberWithUnsignedInt:(*i);
NSNumber *nbuf = [NSNumber numberWithUnsignedInt:(*buf);

我也尝试了通过互联网找到的所有重装内容

但这些都不起作用。

#import "Controller.h"
#import "HeartRateMonitorAppDelegate.h"

static const CGFloat kZDistanceBetweenLayers = 20.0;

static NSString *const bindingsPlot   = @"Bindings Plot";
static NSMutableArray *contentArray;

@interface Controller()

@property (nonatomic, readwrite, strong) IBOutlet CPTGraphHostingView *hostView;

@property (nonatomic, readwrite, strong) CPTXYGraph *graph;
@property (nonatomic, readwrite, strong) CPTPlotSpaceAnnotation *symbolTextAnnotation;

-(void)setupGraph;
-(void)setupAxes;
-(void)setupScatterPlots;

@end

#pragma mark -

@implementation Controller

@synthesize hostView;

@synthesize graph;
@synthesize symbolTextAnnotation;


+(void)initialize
{
    [NSValueTransformer setValueTransformer:[CPTDecimalNumberValueTransformer new] forName:@"CPTDecimalNumberValueTransformer"];
}

-(void)awakeFromNib
{
    [super awakeFromNib];

    self.xShift = 0.0;
    self.yShift = 0.0;

    [self setupGraph];
    [self setupAxes];
    [self setupScatterPlots];
}

-(id)newObject:(uint32 *) buf :(uint32 *) i
{
    NSLog(@"buf = %d", *buf);

    NSNumber *x1 = @(*i);
    NSNumber *y1 = @(*i);

    return @{
             @"x": x1,
             @"y": y1
             };
}

#pragma mark -
#pragma mark Graph Setup Methods

-(void)setupGraph
{
    // Create graph and apply a dark theme
    CPTXYGraph *newGraph = [[CPTXYGraph alloc] initWithFrame:NSRectToCGRect(self.hostView.bounds)];
    CPTTheme *theme      = [CPTTheme themeNamed:kCPTDarkGradientTheme];

    [newGraph applyTheme:theme];
    self.hostView.hostedGraph = newGraph;
    self.graph                = newGraph;

    // Graph padding
    newGraph.paddingLeft   = 0.0;
    newGraph.paddingTop    = 0.0;
    newGraph.paddingRight  = 0.0;
    newGraph.paddingBottom = 0.0;

    // Plot area delegate
    newGraph.plotAreaFrame.plotArea.delegate = self;
}

-(void)setupAxes
{
    // Setup scatter plot space
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;

    plotSpace.allowsUserInteraction = YES;
    plotSpace.delegate              = self;

    // Grid line styles
    CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
    majorGridLineStyle.lineWidth = 0.75;
    majorGridLineStyle.lineColor = [[CPTColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75];

    CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
    minorGridLineStyle.lineWidth = 0.25;
    minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];

    CPTMutableLineStyle *redLineStyle = [CPTMutableLineStyle lineStyle];
    redLineStyle.lineWidth = 10.0;
    redLineStyle.lineColor = [[CPTColor redColor] colorWithAlphaComponent:0.5];

    // Axes
    // Label x axis with a fixed interval policy
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
    CPTXYAxis *x          = axisSet.xAxis;
    x.majorIntervalLength         = CPTDecimalFromDouble(0.5);
    x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
    x.minorTicksPerInterval       = 2;
    x.majorGridLineStyle          = majorGridLineStyle;
    x.minorGridLineStyle          = minorGridLineStyle;
    NSArray *exclusionRanges = @[[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(1.99) length:CPTDecimalFromDouble(0.02)],
                                 [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.99) length:CPTDecimalFromDouble(0.02)],
                                 [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(2.99) length:CPTDecimalFromDouble(0.02)]];
    x.labelExclusionRanges = exclusionRanges;



    // Label y with an automatic label policy.
    CPTXYAxis *y = axisSet.yAxis;
    y.labelingPolicy              = CPTAxisLabelingPolicyAutomatic;
    y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
    y.minorTicksPerInterval       = 2;
    y.preferredNumberOfMajorTicks = 8;
    y.majorGridLineStyle          = majorGridLineStyle;
    y.minorGridLineStyle          = minorGridLineStyle;
    y.labelOffset                 = 10.0;
    exclusionRanges               = @[[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(1.99) length:CPTDecimalFromDouble(0.02)],
                                      [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.99) length:CPTDecimalFromDouble(0.02)],
                                      [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(3.99) length:CPTDecimalFromDouble(0.02)]];
    y.labelExclusionRanges = exclusionRanges;
}

-(void)setupScatterPlots
{
    static BOOL hasData = NO;

    // Create one plot that uses bindings
    CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];

    boundLinePlot.identifier = bindingsPlot;

    CPTMutableLineStyle *lineStyle = [boundLinePlot.dataLineStyle mutableCopy];
    lineStyle.miterLimit        = 1.0;
    lineStyle.lineWidth         = 2.0;
    lineStyle.lineColor         = [CPTColor redColor];
    boundLinePlot.dataLineStyle = lineStyle;

    [self.graph addPlot:boundLinePlot];
    [boundLinePlot bind:CPTScatterPlotBindingXValues toObject:self withKeyPath:@"arrangedObjects.x" options:nil];
    [boundLinePlot bind:CPTScatterPlotBindingYValues toObject:self withKeyPath:@"arrangedObjects.y" options:nil];

    // Set plot delegate, to know when symbols have been touched
    // We will display an annotation when a symbol is touched
    boundLinePlot.delegate                        = self;
    boundLinePlot.plotSymbolMarginForHitDetection = 5.0;


    if ( !hasData ) {
        // Add some initial data
        contentArray = [NSMutableArray arrayWithCapacity:100];
        for ( NSUInteger i = 0; i < 5; i++ ) {
            NSNumber *x = @(1.0 + i * 0.05);
            NSNumber *y = @(1.2 * arc4random() / (double)UINT32_MAX + 1.2);
            [contentArray addObject:@{ @"x": x,
                                       @"y": y }
            ];
        }

        self.content = contentArray;
        hasData      = YES;
    }

    // Auto scale the plot space to fit the plot data
    // Extend the y range by 10% for neatness
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
    plotSpace.allowsMomentum = YES;

    [plotSpace scaleToFitPlots:@[boundLinePlot]];
    CPTPlotRange *xRange        = plotSpace.xRange;
    CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
    [yRange expandRangeByFactor:CPTDecimalFromDouble(1.1)];
    plotSpace.yRange = yRange;

    // Restrict y range to a global range
    plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(10.0)];
    plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(5.0)];

    // set the x and y shift to match the new ranges
    CGFloat length = xRange.lengthDouble;
    self.xShift = length - 3.0;
    length      = yRange.lengthDouble;
    self.yShift = length - 2.0;
}

-(void)insertData:(uint32 *) buf :(uint32 *) i
{
    NSNumber *ni = @(*i);
    //NSNumber *nbuf = @(*buf);

    [contentArray addObject:@{ @"x": ni,
                               @"y": ni }
     ];
    self.content = contentArray;

    [graph reloadData];
}

#pragma mark -
#pragma mark Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
        return 8;
    }
    else {
        return [self.arrangedObjects count];
    }
}

-(id)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSNumber *num;

    if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
        num = @( (index + 1) * (index + 1) );
        if ( [plot.identifier isEqual:bindingsPlot] ) {
            num = @(num.integerValue - 10);
        }
    }
    else {
        NSString *key = (fieldEnum == CPTScatterPlotFieldX ? @"x" : @"y");
        num = (self.arrangedObjects)[index][key];
        if ( fieldEnum == CPTScatterPlotFieldY ) {
            num = @([num doubleValue] + 1.0);
        }
    }
    return num;
}

-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
    if ( [(NSString *)plot.identifier isEqualToString : bindingsPlot] ) {
        return (id)[NSNull null]; // Don't show any label
    }
    else if ( [(NSString *)plot.identifier isEqualToString : bindingsPlot] && (index < 4) ) {
        return (id)[NSNull null];
    }
    else if ( index % 4 ) {
        return (id)[NSNull null];
    }
    else {
        return nil; // Use default label style
    }
}

#pragma mark -
#pragma mark CPTScatterPlot delegate method

-(void)scatterPlot:(CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
    CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;

    if ( annotation ) {
        [self.graph.plotAreaFrame.plotArea removeAnnotation:annotation];
        self.symbolTextAnnotation = nil;
    }

    // Setup a style for the annotation
    CPTMutableTextStyle *hitAnnotationTextStyle = [CPTMutableTextStyle textStyle];
    hitAnnotationTextStyle.color    = [CPTColor whiteColor];
    hitAnnotationTextStyle.fontSize = 16.0f;
    hitAnnotationTextStyle.fontName = @"Helvetica-Bold";

    // Determine point of symbol in plot coordinates
    NSDictionary *dataPoint = (self.arrangedObjects)[index];

    NSNumber *x = dataPoint[@"x"];
    NSNumber *y = dataPoint[@"y"];

    NSArray *anchorPoint = @[x, y];

    // Add annotation
    // First make a string for the y value
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setMaximumFractionDigits:2];
    NSString *yString = [formatter stringFromNumber:y];

    // Now add the annotation to the plot area
    CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle];
    annotation              = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:self.graph.defaultPlotSpace anchorPlotPoint:anchorPoint];
    annotation.contentLayer = textLayer;
    annotation.displacement = CGPointMake(0.0, 20.0);
    [self.graph.plotAreaFrame.plotArea addAnnotation:annotation];
    self.symbolTextAnnotation = annotation;
}


#pragma mark -
#pragma mark Plot area delegate method

-(void)plotAreaWasSelected:(CPTPlotArea *)plotArea
{
    // Remove the annotation
    CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;

    if ( annotation ) {
        [self.graph.plotAreaFrame.plotArea removeAnnotation:annotation];
        self.symbolTextAnnotation = nil;
    }
}

#pragma mark -
#pragma mark PDF / image export

-(IBAction)exportToPDF:(id)sender
{
    NSSavePanel *pdfSavingDialog = [NSSavePanel savePanel];

    [pdfSavingDialog setAllowedFileTypes:@[@"pdf"]];

    if ( [pdfSavingDialog runModal] == NSOKButton ) {
        NSData *dataForPDF = [self.graph dataForPDFRepresentationOfLayer];
        [dataForPDF writeToURL:[pdfSavingDialog URL] atomically:NO];
    }
}

-(IBAction)exportToPNG:(id)sender
{
    NSSavePanel *pngSavingDialog = [NSSavePanel savePanel];

    [pngSavingDialog setAllowedFileTypes:@[@"png"]];

    if ( [pngSavingDialog runModal] == NSOKButton ) {
        NSImage *image            = [self.graph imageOfLayer];
        NSData *tiffData          = [image TIFFRepresentation];
        NSBitmapImageRep *tiffRep = [NSBitmapImageRep imageRepWithData:tiffData];
        NSData *pngData           = [tiffRep representationUsingType:NSPNGFileType properties:nil];
        [pngData writeToURL:[pngSavingDialog URL] atomically:NO];
    }
}

#pragma mark -
#pragma mark Printing

-(IBAction)printDocument:(id)sender
{
    NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];

    NSRect printRect = NSZeroRect;

    printRect.size.width  = (printInfo.paperSize.width - printInfo.leftMargin - printInfo.rightMargin) * printInfo.scalingFactor;
    printRect.size.height = (printInfo.paperSize.height - printInfo.topMargin - printInfo.bottomMargin) * printInfo.scalingFactor;

    self.hostView.printRect = printRect;

    NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:self.hostView printInfo:printInfo];
    [printOperation runOperationModalForWindow:self.hostView.window
                                      delegate:self
                                didRunSelector:@selector(printOperationDidRun:success:contextInfo:)
                                   contextInfo:NULL];
}

-(void)printOperationDidRun:(NSPrintOperation *)printOperation success:(BOOL)success contextInfo:(void *)contextInfo
{
    // print delegate
}

1 个答案:

答案 0 :(得分:0)

Core Plot期望数据值为NSNumber个实例,而不是普通整数。如果需要保留完整的小数精度,可以使用NSDecimalNumberNSNumber的子类)。

由于您使用绑定到NSArrayController的数据,-reloadData及相关方法将无效。这些仅在通过数据源提供数据时使用。这是iOS上唯一可用的方法,这就是为什么网上的大部分示例代码和演示都使用它。

初始化NSArrayController后,您应该使用其方法添加或删除数据,而不是直接更新content数组。 CPTTestAPP 演示使用-insertObject:atArrangedObjectIndex:-removeObjectAtArrangedObjectIndex:来执行此操作。