不调用在单独的Object中实现的Core Plot DataSource委托方法

时间:2012-07-31 18:58:28

标签: macos delegates datasource core-plot

我有两个类,GraphViewController和AppController。 AppController(委托)实现GraphViewController的数据源协议。我遇到的问题是GraphViewController没有调用那些方法。

但是,当我将GraphViewController的数据源设置为self并将协议方法保留在GraphViewController中时(就像CorePlot中提供的CorePlot示例一样)一切正常,没有调用任何reloadData或setNeedsDisplay方法。

问题不在于视图的设置。主题和轴被绘制得很好,只是缺少情节。

对于非常相似的问题,所提供的答案都没有解决我的特定问题。我想(或希望)这只是我想念的一件小事,但我找不到它。

请参阅以下两个类的来源。哦,顺便说一句:这是针对OS-X而不是iOS。

GraphViewController.h:

#import <Cocoa/Cocoa.h>
#import <CorePlot/CorePlot.h>

@interface GraphViewController : NSObject{

    IBOutlet CPTGraphHostingView *graphHostingViewOutlet;
    CPTXYGraph *graph;
}

@property (weak) id<CPTPlotDataSource> delegate;

@end

GraphViewController.m:

#import "GraphViewController.h"

@implementation GraphViewController

@synthesize delegate;

-(void)awakeFromNib {

    [super awakeFromNib];

    // create graph
    graph = [(CPTXYGraph *)[CPTXYGraph alloc] initWithFrame:CGRectZero];

    // apply theme to graph
    [graph applyTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];

    // connect graph to host view
    graphHostingViewOutlet.hostedGraph = graph;

    // get a pointer to the default plot space of the graph
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

    // setup axes limits
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(-0.2f) length:CPTDecimalFromFloat(1.2f)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(-0.2f) length:CPTDecimalFromFloat(1.2f)];

    // get a pointer to the axis set of the graph
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;

    // get the x axis element of the axis set and set propertys for x axis
    CPTXYAxis *x = axisSet.xAxis;
    x.majorIntervalLength = CPTDecimalFromFloat(0.2f);

    // get the y axis element of the axis set and set propertys for y axis
    CPTXYAxis *y = axisSet.yAxis;
    y.majorIntervalLength = CPTDecimalFromFloat(0.2f);

    // create a new plot
    CPTScatterPlot *dataSourceLinePlot = [[CPTScatterPlot alloc] init];

    // set the identifier for the plot
    dataSourceLinePlot.identifier = @"ThePlot";

    // set data source for plot
    dataSourceLinePlot.dataSource = delegate;

    // add the plot to the graph
    [graph addPlot:dataSourceLinePlot];

}

@end

AppController.h:

#import <Foundation/Foundation.h>
#import "GraphViewController.h"
#import <CorePlot/CorePlot.h>

@interface AppController : NSObject <CPTPlotDataSource>

@property (weak) GraphViewController *graphViewController;

- (IBAction)doSomething:(id)sender; // connected to a button

@end

AppController.m:

#import "AppController.h"

@implementation AppController{

    NSArray *_plotData;

}

@synthesize graphViewController = _graphViewController;

-(void)awakeFromNib {

    [super awakeFromNib];

    [_graphViewController setDelegate:self];

    // create data array
    NSMutableArray *newData = [NSMutableArray array];

    for (NSUInteger i = 0; i < 20; i++ ) {

        // create random y values
        id y = [NSDecimalNumber numberWithFloat: rand() / (float)RAND_MAX];

        [newData addObject: [NSDictionary dictionaryWithObjectsAndKeys:

                             [NSDecimalNumber  numberWithFloat:0.05 * i],      // x object
                             [NSNumber numberWithInt:CPTScatterPlotFieldX],    // key
                             y,                                                // y object
                             [NSNumber numberWithInt:CPTScatterPlotFieldY],    // key
                             nil]];
    } // end of for

    _plotData = newData;
}

- (IBAction)doSomething:(id)sender{ // connected to a working button

    NSLog(@"Button was pressed.");

    // tell the graphViewController to reload its data from its delegate (me), but how?

    // this does not work: [[NSNotificationCenter defaultCenter] postNotificationName:@"CPTGraphNeedsRedrawNotification" object:nil];

}

// implementation of delegate methods

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSDecimalNumber *num = [[_plotData objectAtIndex:index] objectForKey:[NSNumber numberWithLongLong:fieldEnum]];
    NSLog(@"numberForPlot was called, num is %@",num);
    return num;
}

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    NSLog(@"numberForPlot was called.");
    return _plotData.count;
}

@end

我希望一旦发现错误,我发布的来源可以作为其他人的简单原型。

2 个答案:

答案 0 :(得分:1)

检查以确保在配置绘图时delegate中已设置-[GraphViewController awakeFromNib]。如果此类在app控制器之前初始化,则它尚未设置。修复方法是为delegate属性添加一个自定义setter,它将新值设置为plot数据源。

答案 1 :(得分:0)

我不打算在这里回答我自己的问题(我仍然没有解决问题的方法),但我有一个暗示让人们试图做同样的事情:

还有另一种方法可以将数据从单独的类提供给使用绑定绘制数据的类。您可以将(核心数据)实体(即dataToPlot)绑定到NSArrayController,然后在绘图类中定义NSArrayController类型的IBOutlet,并使用IB将ArrayController(绑定到plotData)连接到该IBOutlet。这对我有用,似乎是一种不易出错且更优雅的方法。

this coreplot-group thread中详细介绍了设置此步骤所需的步骤。