3

これはCocoan00bの質問です-私は他の環境で何年もGUIアプリケーションをプログラミングしてきましたが、次の些細な状況での「慣用的なCocoa」とは何かを理解したいと思います。

NSViewユーザーがその中に簡単な形を描くことができる簡単な習慣があります。そのdrawRect実装は次のようになります。

- (void)drawRect:(NSRect)rect
{
    // Draw a white background.
    [[NSColor whiteColor] set];
    NSRect bounds = [self bounds];
    [NSBezierPath fillRect:bounds];

    [[NSColor blackColor] set];

    // 'shapes' is a NSMutableArray instance variable
    // whose elements are NSValues, each wrapping an NSRect.
    for (NSValue *value in shapes)
    {
        NSRect someRect;
        [value getValue:&someRect];
        [self drawShapeForRect:someRect];
    }

    // In addition to drawing the shapes in the 'shapes'
    // array, we draw the shape based on the user's
    // current drag interaction.
    [self drawShapeForRect:[self dragRect]];
}

このコードがいかに単純であるかがわかります。shapes配列インスタンス変数は、drawRectメソッドが形状を描画するために使用するモデルとして機能します。ユーザーがマウスダウン/ドラッグ/マウスアップシーケンスを実行するたびに新しいNSRectが追加されます。これもこのカスタムビューに実装されています。shapesこれが私の質問です:

これが「本物の」Cocoaアプリケーションである場合、カスタムビューがモデルを更新するための慣用的な方法は何でしょうか。

つまり、カスタムビューは、別の図形を図形のリストに追加する必要があることをコントローラーにどのように通知する必要がありますか?現在、ビューはそれ自体NSMutableArrayで形状を追跡します。これは実装の詳細としては問題ありませんが、カスタムビューのパブリックAPIの一部としてこの配列を公開したくありません。さらに、エラーチェック、保存/読み込み、元に戻すコードを、カスタムビュー全体に散らかすのではなく、コントローラーのような一元化された場所に配置したいと思います。他のGUIプログラミング環境での過去の経験では、モデルはコントローラーレイヤーのオブジェクトによって管理され、ビューは通常、モデルを直接更新しません。むしろ、ビューは、何かが発生したとき、イベントをディスパッチすること、またはを呼び出すことによって通信します。コントローラー上のメソッドへの参照があるか、同様に分離されたアプローチを使用します。

私の直感では、慣用的なCocoaコードはdelegate、カスタムビューのプロパティを公開し、MyDocumentコントローラーオブジェクト(またはドキュメントコントローラーからぶら下がっている別のコントローラーレイヤーオブジェクト)を、xibファイルのデリゲートとしてビューにワイヤリングします。次に、ビューshapeAdded:(NSRect)shapeはデリゲートのようないくつかのメソッドを呼び出すことができます。ただし、これを行う方法は他にもたくさんあるようです。たとえば、コントローラーにモデルオブジェクト(形状のリスト)への参照をカスタムビューに直接渡す(気分が悪い)、ビューに通知をディスパッチさせるなどです。コントローラーがリッスンし(扱いにくいと感じます)、コントローラーがモデルを更新します。

4

3 に答える 3

5

代理人を持つことは、これを行うための大げさな方法です。もう1つの方法は、ビューでNSArrayバインディングを公開し、それを配列コントローラーのarrangedObjectsバインディングにバインドしてから、配列コントローラーのバインディングcontentを、モデルオブジェクトを保持する実際の配列を所有するものにバインドすることです。次に、アクティブレイヤー内のオブジェクトのリストなど、同じアレイコントローラーに他のビューを追加できます。

これはカスタムビューであるため、IBプラグインを作成してIBのバインディングを公開するか、ビューにbind:toObject:withKeyPath:options:メッセージを送信してプログラムでバインドする必要があります。

于 2009-03-25T12:10:12.270 に答える
2

あなたの /Developer/Examples/AppKit/Sketch ディレクトリには、あなたがやっていることのより高度なバージョンですが、それにもかかわらず適切な非常に良いサンプル xcode プロジェクトがあります。コントローラーとビューの間のバインディングを使用して、物事を行う「正しい」方法を明らかにする素晴らしい例があります。この例では IB プラグインを使用していないため、bind への手動呼び出しと実装されている監視メソッドを確認できます。

于 2009-03-25T15:16:54.507 に答える
1

コードとNSTableViewの間にはいくつかの類似点があるため、データソース(デリゲートと同様)またはバインディングを使用することを検討します。

于 2009-03-25T12:09:20.697 に答える