Cocoaフレームワークの設計パターンに関連する基本的な質問があります。
デリゲートとデータソースの違いは何ですか?
両方とも@protocols
宣言を使用できますが、一部のクラスまたはフレームワークはdelegate
を使用し、他の一部はdatasource
を使用しています。
UI/NSTableView
から理解できるのは、UI関連のイベントに応答するdelegate
だけですが、datasource
はデータに完全に関連しています。しかし、CocoaのUIクラス以外のデータソースの実装は知りません。
注:
デリゲートとデータソースのパターンはほとんど独立しており、直交しています。
デリゲートパターンはCocoaで非常に一般的であり、デリゲート(OS X 10.6より前の非公式のデリゲートプロトコルを実装するインスタンス、または正式なデリゲート@protocol
(10.6以降)オブジェクトインスタンスの動作を変更します。このパターンは、サブクラス化の代わりによく使用されます。クラスをサブクラス化して動作を変更する代わりに、適切なメソッドに応答するデリゲートを提供します。デリゲートを使用するクラスは、契約イベントでメッセージをデリゲートに送信します。クラスとデリゲート間のAPIはクラスによって定義され、パターンを使用するクラスごとに異なりますが、APIは通常、特定のイベントの処理方法をデリゲートに要求するメッセージで構成されます。サブクラス化に対するデリゲートパターンの利点の1つは、クラスが複数のデリゲートプロトコルを実装し、そのインスタンスが複数のクラスのデリゲートとして機能できることです。同様に、オブジェクトインスタンスを他の複数のオブジェクトのデリゲートにすることができます(したがって、ほとんどのデリゲートAPIは、オブジェクトをAPIの各メッセージへの最初の引数として渡します)。デリゲートパターンは他のUIフレームワークでは一般的ではありません(ただし、QtはModel/Viewフレームワークでデリゲートパターンを使用します)notは、本質的に型指定された関数である.Net/CLRデリゲートと同じですポインター。
データソースパターンは、NSBrowser、NSTableView、NSOutlineViewなどの複雑な状態データを持つCocoaのNSView
サブクラスでよく使用されます。データソースプロトコルは、これらの(およびその他の)クラスのインスタンスをAPIで定義しますビューに表示するデータを取得するために使用できます。 NSController
およびCocoa Bindingsアーキテクチャは、データソースパターンの多くの用途に取って代わりましたが、依然として一般的で非常に強力です。上記のデリゲートパターンと同様に、その力の一部は、複数のデータソースを使用するインスタンス(および、場合によっては異なるデータソースプロトコルを持つ複数のクラスのインスタンス)のデータソースとして機能できるオブジェクトに由来します。データソースパターンは、Qt(モデルがデータソースに類似しているModel/Viewフレームワーク内)やWPF/Silverlight(データソースがビューモデルにより密接に類似している場合がある)など、他のUIフレームワークで一般的に使用されます)。
データソースはデータを提供し、デリゲートは動作を提供します。
[〜#〜] mvc [〜#〜] では、データソースはモデル層にあり、デリゲートは制御層にあります。
実際に、考え直してみると、データソースは通常、モデルの近くにある、下にあるコントローラーです。モデルオブジェクトをデータソースとして使用したことはないと思います。
質問に答える前に、委任設計パターンをよりよく理解する必要があります。質問から始めましょう。
デフォルトでは、TableViewは次のようになります:
UITableViewは、表示するセルの数をどのように知るのですか?各セルに何を表示しますか?
委任とは何かを知ったので、OPの実際の質問に答えます。
主に意味の違いの大きな問題です。
基盤のデリゲートとデータソースのみを使用する場合(独自のプロトコルを作成するためではない場合)、それは本当に重要ではありません。ただし、カスタムプロトコルを作成する場合は、それらを理解することで、コードをより適切に記述できます(より重要度の高い読み取り、屈折)。
開発者の観点からは、どちらもdelegat-ingクラスとデリゲートクラスの間の相互作用を扱います。
データソースは、デリゲートとほとんど同じです。違いは、委任オブジェクトとの関係です。ユーザーインターフェイスの制御を委任する代わりに、データソースはデータの制御を委任されます。委任オブジェクト(通常はテーブルビューなどのビューオブジェクト)は、データソースへの参照を保持し、ときどき表示するデータを要求します。デリゲートのようなデータソースは、プロトコルを採用し、少なくともそのプロトコルに必要なメソッドを実装する必要があります。データソースは、委任ビューに与えるモデルオブジェクトのメモリを管理します。
レイマンの言葉では:
DataSourceは主にwhatを処理し、通常はそれを行います初期化時。デリゲートは、主にhowおよびfeeds特定の動作、つまりユーザーがこれをクリックした場合...どうなりますか?彼らがスワイプした場合...どうなりますか?
TableViewの例として:
DataSource
その中には何がありますか?どのようなセルを提示していますか? cellForRowAtIndexPath
。
セクションのタイトルは何ですか? titleForHeaderInSection
それらはいくつのセルですか? numberOfRowsInSection
したがって、通常はreturn値です。デリゲートでは、void
型であることがより一般的です。
データソースメソッド
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell // return a cell ie UITableViewCell
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int // return a number ie an Int
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? // return the title ie a String
デリゲートメソッド
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)
一部のデータソースメソッドが返されず、一部のデリゲートメソッドが返されるため、明らかに選択的に選択しました。
デリゲート
フッターの表示が終わったら、何をすべきか/「行動の形態」をどのように使うべきですか、アラートをポップしてほしいですか?didEndDisplayingFooterView
セルにいくつかの追加機能を提供するaccessoryTypeがありますか? accessoryTypeForRowWithIndexPath
私の観点からすると、DataSource
はデータがどこにあるかを知らないオブジェクトなので、提供する必要があります。列内のアイテム数をオブジェクトに伝えるなど。
オブジェクトがデータを表示する部分であるDelegate
は、オブジェクトがデータの場所を知っているが、それを正しく使用する方法を知らないため、クラスによって実装する必要があります。
短くする:
デリゲートは、セルおよびテーブルに対するUIおよびユーザーアクションに関連します。
共通メソッド:willSelectRow、didSelectRow、willDisplay、heightForRow、willBeginEditingAt
データソーステーブルビューでのデータの編集、作成、表示を処理します。
共通メソッドcanEditRowAt、commit、titleForHeaderInSection、cellForRowAt、numberOfSections、sectionIndexTitles
両方ともProtocolであり、今ではProtocolの主な意図は、普遍的なコーディングの実践、またはすべての人に同じコーディングの実践を維持することです(私の知る限り)。 ITableViewDataSource&ITableViewDelegateを使用せずにtableViewを作成していると仮定すると、そうではないような方法でtableViewを作成します。 Protocolが来る、Appleルールのセットを作成する、またはprotocolであり、誰もがそれに従う必要があります。今DataSource&デリゲートは明らかにプロトコルです。理解できる名前を見てDataSourcenumberOfRowsInSectionのようなものを扱います- cellForRowAtIndexPath、numberOfSections何らかの種類のデータを取得/処理するtableViewの場合、およびデリゲートはdidSelectRow、- willSelectRow、heightForRowなど、何らかの種類のUIの変更/アクションに関連するtableViewのように、その命名規則はタスクを分離するための仮説ではありません。データソースがデータを提供し、デリゲートが動作を提供します。