1

私はこれに数日間取り組んできました-モデルの1つから(コントローラーを介して)データをグラフ化するビューに取得することになっているカスタムプロトコルがあります。

これが私がこれを行う方法です-ステップバイステップ:

グラフ表示では、プロトコルを次のように宣言します。

@class GraphView;

@protocol GraphViewDataSource <NSObject>

-(CGFloat)yValueForGraphView:(GraphView *)sender usingXval:(CGFloat)xVal;

@end

次に、view.hでプロパティを宣言します

@interface GraphView : UIView

@property (nonatomic, weak) IBOutlet id <GraphViewDataSource> dataSource;

@end

view.mでプロパティを合成します。

@synthesize dataSource=_dataSource;

次に、drawRectで、このメソッドを呼び出して、別のコントローラーのモデルからCGFloatを戻します。

-(void) drawRect:(CGRect)rect
{
//context stuff, setting line width, etc

CGPoint startPoint=CGPointMake(5.0, 6.0);

NSLog(@"first, y value is: %f", startPoint.y);

startPoint.y=[self.dataSource yValueForGraphView:self usingXval:startPoint.x]; //accessing delegate via property

NSLog(@"now the y value now is: %f", startPoint.y);

//other code..
}

もう1つのViewControllerで、view.hファイルをインポートし、プロトコルに準拠していることを宣言しています。

#import "GraphView.h"

@interface CalculatorViewController () <GraphViewDataSource>

GraphViewのプロパティを作成する:

@property (nonatomic, strong) GraphView *theGraphView;

合成:

@synthesize theGraphView=_theGraphView;

セッターで、現在のコントローラーをdataSource(別名デリゲート)として設定します。

-(void) setTheGraphView:(GraphView *)theGraphView
{
    _theGraphView=theGraphView;
    self.theGraphView.dataSource=self;

}

また、prepareForSegue(修正を探しているときに試したものの1つ)でコントローラーをデリゲートとして設定しました。

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"GraphViewController"])
    {
        self.theGraphView.dataSource=self;
    }
}

最後に、必要なメソッドを実装します。

-(CGFloat)yValueForGraphView:(GraphView *)sender usingXval:(CGFloat)xVal
{
    CGFloat test=51.40; //just to test
    return test;
}

そして、graphViewのdrawRectのテストNSLogから得られる出力は次のとおりです。

2012-10-25 20:56:36.352 ..[2494:c07] first, y value is: 6.000000
2012-10-25 20:56:36.354 ..[2494:c07] now the y value now is: 0.000000

これは、dataSourceを介して51.40を返すはずですが、そうではありません。理由がわからない!私を夢中にさせて、私はすべてを正しくやったようです。しかし、デリゲートメソッドは呼び出されていません。

私が見逃している愚かなことはありますか?


追加情報-コントローラーとGraphViewの図:

GraphingCalc

4

3 に答える 3

1

図は役に立ちます!

あなたがする必要があるのは、カスタムGraphViewを公開するか、デリゲートの設定をラップするGraphViewControllerのメソッドを持つことです。セグエでは、宛先ビューコントローラー(GraphViewController)にアクセスしてから、GraphViewに直接デリゲートを設定するか、GraphViewControllerに自分自身を渡してデリゲートを設定する必要があります。

CalculatorViewControllerが所有するGraphViewにデリゲートを設定しても、GraphViewがシングルトンであるか、GraphViewControllerに渡されない限り、GraphViewControllerのGraphViewに影響を与えることはありません。

GraphViewControllerがそれに含まれるGraphViewであるプロパティを公開すると仮定すると、CalculatorViewControllerのセグエは次のようになります...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Ensure the identifier string matches the segue name from the Storyboard
    if ([segue.identifier isEqualToString:@"GraphViewControllerSegue"])
    {
        // Change this to whatever class is the destination class of the segue
        GraphViewController *graphViewController = (GraphViewController *)[segue destinationViewController];
        self.graphView.delegate = self;
        // Pass the GraphView with the delegate set into the GraphViewController
        graphViewController.graphView = self.graphView;
    }
}

それがボタン対アクションからの直接のセグエであるという事実は無関係です。Storyboard / XIBでセグエに識別子を指定するprepareForSegue:sender:と、が呼び出され、どのセグエが呼び出されているかを判別できます。

また、GraphViewのGraphViewControllerにパブリックプロパティがない場合は...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"GraphViewControllerSegue"])
    {
        // Change this to whatever class is the destination class of the segue
        GraphViewController *graphViewController = (GraphViewController *)[segue destinationViewController];
        [graphViewController setGraphViewDelegate:self];
    }
}

GraphViewControllerの実装には次のものが必要です。

- (void)setGraphViewDelegate:(id)graphViewDelegate {
    // Set the delegate directly in the ivar
    _graphView.delegate = graphViewDelegate;
}
于 2012-10-28T22:53:49.273 に答える
0

私がこれを解決した方法は、いくつかのデリゲートをチェーンすることでした。私は次のメソッドでGraphViewaを宣言します。protocol GraphViewDelegate

-(float)ordinateForAbscissa:(float)abscissa forGraph:(GraphView *)requestor;
-(float)scaleForGraph(GraphView *)requestor;

このプロトコルはによって実装され、彼はコントローラーがロードされるときのとしてGraphViewController自分自身を設定します。delegateGraphViewviewDidLoad

これで、から呼び出されるCalculatorControllerDelegate実装を行う別のデリゲートがあります。このプロトコルを実装し、セグエの際に自分自身をのデリゲートとして設定します。yCoordinateForXordinateForAbscissaCalculatorViewControllerGraphViewController

お役に立てれば。

于 2012-10-30T00:42:39.743 に答える
0

これが最終的な解決策です:

GraphViewControllerは、最初にGraphViewのデリゲートを設定する必要がありました。これは、graphViewが(カスタムUIViewとして)GraphViewControllerに接続されており、graphViewの特定のインスタンスが使用できないため、他のクラスから設定できないことがわかりました。

カスタムビュー(私の場合はgraphView)に情報を取得する方法は、カスタムビューのコントローラーで別のプロトコルを設定することです。次に、別のクラスをそのコントローラーのデリゲートとして設定し、最初にコントローラーにデータを渡し、次にカスタムビューにデータを渡します。

非常に重要なことの1つは、ストーリーボードを操作する場合、コントローラーのデリゲートをprepareForSegueに設定する必要があることです(reckerbhで言及されています)。私の場合、CalculatorViewControllerはGraphViewControllerに接続されているため、perpareForSegueは次のようになります。

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"ShowGraph"])
    {
        GraphViewController *gvc=[segue destinationViewController];
        gvc.yValueSource=self;
    }
}

ここで、[seguedestinationViewController]を介してGraphViewControllerの既存のインスタンスへの新しいポインターを作成していることに注意してください。alloc initを介して新しいものを作成していません。これは、すでに持っているものとは接続されず、完全に無関係になるためです。

したがって、ここでの主なアドバイスは、デリゲートを設定するときに同じインスタンスを使用していることを確認することだと思います。また、そのインスタンスにアクセスできない場合は、二重委任を使用します(または、必要に応じて3倍にすることもできます)。

于 2012-10-30T22:55:45.103 に答える