カスタムビューはモデルオブジェクトをどのように更新する必要がありますか?
-
22-08-2019 - |
質問
これはココアN00Bの質問です - 私は他の環境で長年GUIアプリケーションをプログラミングしてきましたが、今では次の些細な状況について「慣用的なcoco」とは何かを理解したいと思います。
簡単なカスタムがあります 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
sが追加されます shapes
ユーザーがマウスダウン/ドラッグ/マウスアップシーケンスを実行するたびに、このカスタムビューでも実装しました。これが私の質問です:
これが「実際の」ココアアプリケーションである場合、カスタムビューがモデルを更新するための慣用的な方法は何でしょうか?
言い換えれば、カスタムビューは、形状のリストに別の形状を追加する必要があることをコントローラーにどのように通知する必要がありますか?今、ビューは独自の形状を追跡します NSMutableArray
, 、これは実装の詳細として問題ありませんが、カスタムビューのパブリックAPIの一部としてこの配列を公開したくありません。さらに、カスタムビュー全体に散らばるのではなく、コントローラーのような中央の場所でコードをエラーチェック、保存/ロード、元に戻すことをお勧めします。他のGUIプログラミング環境での私の過去の経験では、モデルは私のコントローラーレイヤーのオブジェクトによって管理されており、ビューは一般に直接更新されません - むしろ、イベントを派遣するか、電話をかけることによって、何かが起こったときにビューが通信します。メソッドコントローラーには、同様に分離されたアプローチを参照するか、使用しています。
私の腸の感覚は、慣用的なココアコードが暴露するということです delegate
私のカスタムビューのプロパティ、そして MyDocument
コントローラーオブジェクト(またはドキュメントコントローラーからぶら下がっている別のコントローラーレイヤーオブジェクト)は、その代表としてXIBファイルに表示されます。その後、ビューは次のような方法を呼び出すことができます shapeAdded:(NSRect)shape
代表者。しかし、これを行うには、モデルオブジェクト(シェイプのリスト)への参照をカスタムビュー(間違っていると感じます)に渡すなど、これを行う他の数の方法があるようです。コントローラーが聴く(扱いにくいと感じる)、そしてコントローラーがモデルを更新すること。
解決
代表者を持つことはaです クロムレント これを行う方法。もう1つの方法は、ビューにnsarrayバインディングを公開し、それをアレイコントローラーに結合することです arrangedObjects
バインディング、次にアレイコントローラーをバインドします content
モデルオブジェクトを保持している実際の配列を所有するものにバインドします。その後、アクティブレイヤーのオブジェクトのリストなど、同じアレイコントローラーに他のビューを追加できます。
これはカスタムビューであるため、IBPluginを作成してIBのバインディングを公開するか、ビューを[a]に送信してプログラムで結合する必要があります。 バインド:Toobject:withkeypath:options: メッセージ。
他のヒント
/開発者/例/appkit/sketchディレクトリには、あなたがしていることのより高度なバージョンである非常に良い例Xcodeプロジェクトがありますが、それでも適切です。コントローラーとビューの間でバインディングを使用して、物事を行う「正しい」方法に光を当てる素晴らしい例があります。この例ではIBプラグインは使用されないため、バインドする手動呼び出しと実装されたメソッドの観察方法を確認できます。
コードとnStableViewの間にはいくつかの類似点があるので、データソース(デリゲートと同様)またはおそらくバインディングを使用することを検討します。