0

我有两个类,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

应用控制器.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

应用控制器.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

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

4

2 回答 2

1

在配置绘图时检查以确保delegate已设置。-[GraphViewController awakeFromNib]如果这个类在应用控制器之前被初始化,它还不会被设置。解决方法是为属性添加一个自定义设置器,该delegate属性也将新值设置为绘图数据源。

于 2012-08-01T23:40:46.703 回答
0

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

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

此 coreplot-group 线程中更详细地描述了设置所需的步骤。

于 2012-08-01T15:31:00.940 回答