Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 260 - プロトコールとデリゲーション ProtocolsとDelegation

2016年10月17日:Swift3向けにイメージを変更*1

FaceView(V)とHappinessViewController(C)を繋げていくためにプロトコールとデリゲーションの復習をします。

プロトコールの復習。これで何度目になるだろう?

復習をすればするほど理解は深まっていく実感はありますが、ペースが非常に遅いんで情けないです(T_T) このブログに読者が5人*2いるけど、「何やってんだ。おせーな。つきあってらんねーよ」という言葉が聞こえてきそうです(^^;)

今までのプロトコールとデリゲーションに関する記事を並べてみると...

まだまだデリゲーションを完全に自分のモノにしたとは言いがたいのですが、今回ポール先生の講義を聴いて、デリゲーションの実装の仕方は理解できたと思います。

Viewクラス(UIViewクラス)とControllerクラス(UIViewController)の関係性を使ってプログラムする例を考えてみたら理解しやすかったです。

6ステップ プロトコール・デリゲーション実装法

UIViewクラスのオブジェクト(インスタンス)はジェネリック(一般的)な存在なので表示機能は備わっていても、何を表示するか具体的なコンテンツを知る必要はありません。そのため、コンテンツの内容に関して他のオブジェクトに任せる必要があります。この任せることをデリゲーション(委譲)と呼びます。ちょっと分かりにくいのですが、処理を任されたオブジェクトのことをデリゲートと呼びます。すなわちUIViewControllerクラスのオブジェクトがデリゲートということです。日本語が妙なんですが気にしないで、デリゲーションの説明をします。

f:id:yataiblue:20161017172804j:plain

2つのクラスをカスタムに

  1. AViewクラスがAControllerクラスに任せたい(デリゲーション)処理をデリゲート・プロトコールとして用意します。ViewクラスにあるcontrolValueを外部のオブジェクトで操作してもらいたい(委任)のですが、この値を操作する関数「getControlValue(sender:)」をプロトコールとしてパブリックにオープンにします。
  2. デリゲート・プロトコールとして、デリゲート・プロパティをAViewクラス内で保持します。初期化ステップが発生するまで変更が加わらないようにするためにオプショナル設定にします。また循環参照を避けるためにweakにしてメモリーリークを回避します。
  3. デリゲート・プロパティにAViewである自分自身(self)を引数として与えることで、controlValueの具体的な値を取り出してきます。ここを理解できるとプロトコールとデリゲーションの関係が理解できたと言えるでしょう。基本的にdelegateというプロパティは、AControllerクラス内で自分自身である(AController)を指定しているため、このdelegateはAControllerクラスで記述している「getControlValue(sender:)」メソッドのみを持つ「AViewDelegateData型」になっているんです。ということで「delegate?.getControlValue(sender: self)」 でAControllerで記述されているメソッドを利用して具体的なInt型の値を取り出すことができます。
  4. 処理を委任(デリーゲート)されたAControllerクラスに先ほどのプロトコールを準拠させます。
  5. 先ほど説明したAController自身をAViewクラスのプロパティ(delegate)に指定することで、delegateは「AViewDelegateData型」になります。このステップは、コードを書いて実装する場合に必ず必要ですが、Xcode8を使って設定する方法もいくつかあります。次のリンクに説明があります。Swiftで遊ぼう! - 318 - My Picker Project : SingleComponentPicker Xcodeでデリゲーション - Swiftで遊ぼう! on Hatena
  6. プロトコールはブループリントなので、ここで具体的な処理をコードします。

以上! 異なるクラスをプロトコールを使って繋げることができます。

重要iOS API利用時は、上記のステップ(1-3)を必要としません。例えば、UIViewクラスやサブクラスなど、ジェネリックなクラスは、表示機能のみ受け持ち、コンテンツの内容と表示に関わる具体的な制御をデリゲーション(委譲)させるため必要なプロトコールを既に用意しています。「DataSource」と「Delegate」という2つのプロトコールがそれです。それぞれ同じデリゲートオブジェクトを指していますが、メソッドが異なります。「DataSource」はコンテンツに関わるもの(表示内容や項目数など)で、「Delegate」は表示に関わるもの(表示位置や配置)です。必ず2つのプロトコールを準拠させて、オプショナル以外の必須メソッドを記述する必要があります。

非常に分かり易かったですね。

今日はここまで。

*1:2015年11月30日:ここの内容はデリゲーションの基本です。完全に理解していないとiOS開発はできません。分からなければ質問して下さい、2015年5月27日追記:説明の補完、2015年5月11日追記:プロトコールとデリゲーションの理解は、iOS API利用のために必須です。「Swiftで遊ぼう! - 301 - Scroll Viewのデリゲート・メソッド」で具体的な実装法をデモンストレーションしています

*2:この記事を書いた時の読者数です。今はちょっと増えてます。読者の皆さんありがとうございますm(_ _)m