現在私は自分自身にiOSプログラミングを教えていますが、頭を包むことが本当に難しいと思う概念の1つは委任です。それは何ですか?なぜ、どのように使用されますか?利点は何ですか?私が読んでいる本からの技術的な執筆は、理解するのを難しくします。
delegates
を理解するには、protocols
を理解する必要があります。
protocol
はサービス契約のようなものです。オブジェクト(ほとんどの場合UIViewController
サブクラスですが、常にではありません)がその契約に署名するとき、「私が送信するメッセージをバックするロジックを提供することに興味があります」と言っています。これは、関心のあるレベルへのサインアップに関してNSNotificationCenter
に似ています。委任を使用するオブジェクトであるという違いは、一度に1つのdelegate
のみを持つことができ、複数のオブジェクトがサインアップできるためです。同じNSNotification
。
Appleは委任を広範に使用しています。しかし、ますます、Apple多くのAPIをblocks
に移動しています。これは、他の言語のcallbacks
に似ています。
とはいえ、委任はそれ自体が設計パターンであると私が主張する場合でも、委任はMVCの維持に役立ちます。コントローラからモデルを分離するのに役立ちます。 John Cartwrightの例のように、UITableView
は行とセクションを表示する方法を知っています。パフォーマンス上の理由からUITableViewCells
を再利用する方法を知っています。 UIScrollView
が知っている他のすべてのものを知っています。しかし、表示するセルがどのかわかりません。これらのセルにデータを入力する内容がわかりません。与えられたNSIndexPath
で再利用するセルがわかりません。とにかく、これは本当にコントローラーの仕事です。委任により、テーブルビューはこの非ビューロジックを、とにかくその責任を負うべきオブジェクトにオフロードできます。
それ以上に、オブジェクトの存続期間全体を通じて1つのデリゲートに縛られることはありません。与えられたUITableView
に対して複数のデータソースを非常に簡単に持ち、必要に応じて実行時にそれらを切り替えることができます。
したがって、一方では、オブジェクトへのデータの供給とオブジェクトからの相互作用への応答には委任が最適です。 UITableView
、UIPickerView
、UICollectionView
などの多くのUIKitクラスに表示されます。
しかし、委任は、オブジェクト間で情報を受け渡したい場合にも非常に役立ちます。独自のプロトコルを非常に簡単に作成し、独自のオブジェクトにサインアップして、それらに従うことができます。さらに、プロトコルメソッドはデフォルトで_@required
_ですが、一部のメソッドを_@optional
_に指定できます。これにより、必要に応じてある程度の柔軟性が得られます。親View Controllerと子View Controllerがあるとしましょう。たぶん、これを行うために新しいContainment APIを使用しています。通常、親から子に情報を渡す必要がある場合は、プロパティを使用してこれを行います。できました。しかし、子から親に情報を渡す必要がある場合はどうでしょうか。たぶん、子供に何か変化があり、親に通知する必要があります。確かに、特定の値でKVOを実行できます。しかし、ボタンがいつ押されたかを知りたい場合があります。子View Controllerで新しいプロトコルを作成するだけです
_@protocol MyChildDelegate
- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController;
@end
@interface MyChildViewController : UIViewController
@property (weak, nonatomic) id <MyChildDelegate> delegate;
@end
_
MyChildViewControllerで、ボタンがタップされたときに、デリゲートがデリゲートメッセージに応答するかどうかを確認します(必要であり、デリゲートがメソッドを実装していない場合、クラッシュします。メソッド_@optional
_を作成できますする必要があります)そしてそれを送ってください:
_- (IBAction)someButtonTapped:(id)sender {
if ([self.delegate respondsToSelector:@selector(buttonWasTappedInChild:)]) {
[self.delegate buttonWasTappedInChild:self];
}
}
_
次に、MyChildViewControllerのデリゲートをself
に設定し、親ビューコントローラに- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController
を実装します。ブーム!あなたは子供から親に渡される情報を持っています。 2つのオブジェクト間の関係は、親/子ほど接近している必要はありません。これはサービスコントラクトなので、必要なメソッドを実装することにより、サインアップするオブジェクトが交渉の終わりを迎える限り、あなたは黄金です!
注:デリゲートは弱い/プロパティを割り当てる必要があります。そうでない場合、どちらのオブジェクトも割り当て解除できない保持サイクルに入ります。
お役に立てれば!
デリゲートは、通常のオブジェクトにこれらの関数を実装することが意味がない場合に、特定の関数を実装するオブジェクトです。依存性注入の一種です。
具体的な例については、UITableViewDelegateプロトコルをご覧ください。テーブルビューの行を選択するためのアクションは、アプリごとに、また場合によってはテーブルビューごとに異なるため、これらのメソッドはテーブルビューを直接実装する意味がありません。デリゲートにはメソッド-tableView:didSelectRowAtIndexPath:
したがって、実装するアクションごとにテーブルビューをサブクラス化せずに、行の選択を処理するオブジェクトを作成できます。